I have a ChartView in QML I'm trying to update from a data model in C , however, I'm running into certain issues where I can't seem to figure out a way to update the LineSeries properly.
My Sample QML Code looks like:
ChartView {
id: dataChartView
animationOptions: ChartView.NoAnimation
theme: ChartView.ChartThemeDark
antialiasing: true
Layout.fillHeight: true
Layout.fillWidth: true
ValueAxis {
id: axisXdata
min: dataManager.xMin
max: dataManager.xMax
}
ValueAxis {
id: axisYdata
min: 0
max: 1
}
LineSeries {
id: dataLineSeries
name: "Angle"
axisX: axisXdata
axisY: axisYdata
}
VXYModelMapper {
id: dataModelMapper
model: dataManager.dataModel[data]
series: dataLineSeries
firstRow: 1
xColumn: 0
yColumn: 1
}
}
The underlying model is a QAbstractTableModel that looks like this:
class DataModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum{
NameRole,
ValueRole
};
explicit DataModel(QObject *parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
void setMaxSize(int maxSize);
int maxSize() const;
Q_INVOKABLE void addData(const QPointF& point);
public:
void handleNewData(const QPointF& point);
private:
QVector<QPointF> m_data;
int m_ModelMaxSize;
signals:
void newDataAdded(const QPointF& point);
};
and the relevant addData()
function simply just pushes the Point into the m_data
vector
void MsclDataModel::addData(const QPointF &point)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_data.push_back(point);
endInsertRows();
}
I then have another class called DataManager
which runs a function in another thread and just adds points to the data model
void DataManager::GeneratePoints()
{
setXMin(QDateTime::currentDateTime().toMSecsSinceEpoch()); // for the min and max on the horizontal axis
for(double t=0 ; ; t =1)
{
double y = (1 sin(t/10.0)) / 2.0;
// many data models are required
for(const auto& model : m_Models)
{
auto time = QDateTime::currentDateTime().toMSecsSinceEpoch();
setXMax(qMax(m_xMax, time));
model->handleNewData(QPointF(time, y));
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
My issue is with this method and with the number of models I have, the application slows to a crawl and crashes eventually after about a minute or so. I've tried to constrain the addData()
function to only show the latest 500 points by using something like this:
void DataModel::addData(const QPointF &point)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
if(m_data.size() == 500)
{
m_data.erase(m_data.begin());
}
m_data.push_back(point);
endInsertRows();
}
However, my output looks something like: where the data model just stops updating after the 500th point.
I've also tried using a List to pop after max size of the list has been reached but the output is still the same. What am I doing wrong here?
CodePudding user response:
Instead of beginInsertRows()
and endInsertRows()
I've used beginResetModel()
and endResetModel()
which works. I assume the range for the beginInsertRows()
is wrong and it doesn't send an update anymore, so it stops drawing. You would probably also need to call beginRemoveRows()
I would stick with a full reset.
void DataModel::addData(const QPointF &point)
{
beginResetModel();
if (m_data.size() == 500) {
m_data.pop_front();
emit xMinChanged();
}
m_data.push_back(point);
emit xMaxChanged();
endResetModel();
}
Edit: This will also work.
void DataModel::addData(const QPointF &point)
{
if (m_data.size() == 500) {
beginRemoveRows(QModelIndex(), 0, 0);
m_data.pop_front();
endRemoveRows();
emit xMinChanged();
}
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_data.push_back(point);
endInsertRows();
emit xMaxChanged();
}