简体   繁体   English

从 C++ 不断更新一个 QML LineSeries ChartView 数据 model

[英]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 看起来像这样: DataModel 停止更新 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM