[英]Continuously update a QML LineSeries ChartView with a data model from C++
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.我在 QML 中有一个 ChartView 我正在尝试从 C++ 中的数据 model 进行更新,但是,我遇到了某些问题,我似乎无法找到正确更新 LineSeries 的方法。
My Sample QML Code looks like:我的示例 QML 代码如下所示:
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:底层 model 是一个 QAbstractTableModel,如下所示:
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相关的 addData addData()
function 只是将 Point 推入m_data
向量
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然后我有另一个 class 称为DataManager
,它在另一个线程中运行 function 并且只是将点添加到数据 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:我试图通过使用如下内容来限制 addData addData()
function 仅显示最新的 500 点:
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:但是,我的 output 看起来像这样: where the data model just stops updating after the 500th point.其中数据 model 在第 500 个点后停止更新。
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.我也尝试过在达到列表的最大大小后使用列表弹出,但 output 仍然相同。 What am I doing wrong here?我在这里做错了什么?
Instead of beginInsertRows()
and endInsertRows()
I've used beginResetModel()
and endResetModel()
which works.我没有使用beginResetModel()
beginInsertRows()
endInsertRows()
endResetModel()
。 I assume the range for the beginInsertRows()
is wrong and it doesn't send an update anymore, so it stops drawing.我假设beginInsertRows()
的范围是错误的,它不再发送更新,所以它停止绘制。 You would probably also need to call beginRemoveRows()
I would stick with a full reset.您可能还需要调用beginRemoveRows()
我会坚持完全重置。
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();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.