Can someone provide a working example of VXYModelMapper with lineseries chart ?
-
I want to implement something like this .With a model from cpp and combined with line charts but I am not able to understand yColumn and xColumn as in what data shall I provide it and I would like to Append the data to the lineseries every time it is updated.
qml: Rectangle { implicitWidth: implicitWidth + 2*anchors.margins implicitHeight: implicitHeight + 2*anchors.margins clip: true color: "#ddd" Item { id: valueDisp implicitWidth: 640 implicitHeight: 640 ChartView { id: chartView title: " Scope " anchors.fill: parent legend.visible: false antialiasing: true backgroundColor: "white" plotAreaColor: "white" titleColor: "white" ValueAxis { id: axisX titleText:componentData.readXAxisName min: componentData.changeXMin max: componentData.changeXMax tickCount: 1 } ValueAxis { id: axisY titleText:componentData.readYAxisName min: componentData.changeYMin max: componentData.changeYMax tickCount: 1 } LineSeries { id: lineSeries name: "Data Output" axisX: axisX axisY: axisY useOpenGL: true VXYModelMapper{ model:componentData.dataRead } } }
cpp:
//this is a snippet of the code I am using : // in class ScopeData I a updating setXdata and setYdata and whenever I update them I assert valueAdded signal as well Q_PROPERTY(QQmlListProperty<ChartData> dataRead READ dataRead NOTIFY valueAdded) QQmlListProperty<ChartData> ScopeData::dataRead() { return QQmlListProperty<xpcv::ChartData> (this,m_chartData); } // these are the functions that I am using to update the data in the chart ChartData::ChartData(QObject *parent) : QObject(parent), m_xValue(0), m_yValue(0) {} void ChartData::setXdata(int data) { m_xValue=data; } void ChartData::setYdata(double data) { m_yValue=data; }
but I get the following error:
unable to assign qmlListProperty<ChartData> to QAbstractItemModel
PS- I cannot share the entire code because of privacy of project details
Thank You,
Saransh Vora -
This subject is rather old but I also have not found any example and I took time to make it work.
Below my proposal
Click on the chart to randomly append datamain.cpp
#include <QQmlEngine> #include <QApplication> #include <QQmlApplicationEngine> #include "chartmodel.h" int main(int argc, char *argv[]) { #if defined(Q_OS_WIN) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #endif QApplication app(argc, argv); //Use QApplication for QChart, QGuiApplication causes a bug qmlRegisterType<ChartModel> ("MainLib", 1, 0, "ChartModel"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
chartmodel.h
#ifndef CHARTMODEL_H #define CHARTMODEL_H #include <QVector> #include <QAbstractTableModel> //#include <QDebug> class ChartModel : public QAbstractTableModel { Q_OBJECT QVector<QPair<double,double>> vec_; double m_xMin; double m_xMax; double m_yMin; double m_yMax; Q_PROPERTY (double xMin READ get_xMin WRITE set_xMin NOTIFY xMinChanged) Q_PROPERTY (double xMax READ get_xMax WRITE set_xMax NOTIFY xMaxChanged) Q_PROPERTY (double yMin READ get_yMin WRITE set_yMin NOTIFY yMinChanged) Q_PROPERTY (double yMax READ get_yMax WRITE set_yMax NOTIFY yMaxChanged) public: explicit ChartModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) 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; double get_xMin() const; double get_xMax() const; double get_yMin() const; double get_yMax() const; public slots: bool set_xMin(double val); bool set_xMax(double val); bool set_yMin(double val); bool set_yMax(double val); void appendData(); signals: void xMinChanged(double); void xMaxChanged(double); void yMinChanged(double); void yMaxChanged(double); }; #endif // CHARTMODEL_H
chartmodel.cpp
#include "chartmodel.h" ChartModel::ChartModel(QObject *parent) : QAbstractTableModel(parent) { m_xMin = 0.; m_xMax = 1.; m_yMin = 0.; m_yMax = 1.; } int ChartModel::rowCount(const QModelIndex & /* parent */) const { return vec_.size(); } int ChartModel::columnCount(const QModelIndex & /* parent */) const { return 2; } QVariant ChartModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); if (index.column() == 0){ return vec_.at(index.row()).first; } if (index.column() == 1){ return vec_.at(index.row()).second; } return QVariant(); } double ChartModel::get_xMin() const { return m_xMin; } double ChartModel::get_xMax() const { return m_xMax; } double ChartModel::get_yMin() const { return m_yMin; } double ChartModel::get_yMax() const { return m_yMax; } bool ChartModel::set_xMin(double val) { bool ret = false; if ((ret = (m_xMin != val))) { m_xMin = val; emit xMinChanged (m_xMin); } return ret; } bool ChartModel::set_xMax(double val) { bool ret = false; if ((ret = (m_xMax != val))) { m_xMax = val; emit xMaxChanged (m_xMax); } return ret; } bool ChartModel::set_yMin(double val) { bool ret = false; if ((ret = (m_yMin != val))) { m_yMin = val; emit yMinChanged (m_yMin); } return ret; } bool ChartModel::set_yMax(double val) { bool ret = false; if ((ret = (m_yMax != val))) { m_yMax = val; emit yMaxChanged (m_yMax); } return ret; } void ChartModel::appendData() { int const nbData = 1+qRound(10.*double(qrand())/double(RAND_MAX)); int const vecSize = vec_.size(); if (!vecSize){ m_xMin = qInf(); m_xMax = -qInf(); m_yMin = qInf(); m_yMax = -qInf(); } beginInsertRows(QModelIndex (), vecSize, vecSize+nbData); for(int seed = 0 ; seed < nbData; ++seed){ double const xVal = vec_.size(); double const yVal = double(qrand())/double(RAND_MAX); set_xMin(qMin(m_xMin, xVal)); set_xMax(qMax(m_xMax, xVal)); set_yMin(qMin(m_yMin, yVal)); set_yMax(qMax(m_yMax, yVal)); vec_.append(qMakePair<double, double>(xVal, yVal)); } endInsertRows(); }
main.qml
import QtQuick 2.10 import QtQuick.Window 2.10 import QtCharts 2.0 import MainLib 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") property ChartModel chartModel : ChartModel{} ChartView { id : chart anchors.fill: parent antialiasing: true animationOptions: ChartView.AllAnimations SplineSeries { id : serie1 axisX : ValueAxis { id: xAxis min: chartModel.xMin max: chartModel.xMax } axisY : ValueAxis { id: yAxis min: chartModel.yMin max: chartModel.yMax } VXYModelMapper { id: mapper xColumn: 0 yColumn: 1 model: chartModel } } MouseArea{ anchors.fill : parent onClicked: { chartModel.appendData() } } } }
-
The "viewport" of the ChartView is defined by the properties ValueAxis:min and ValueAxis:max for both X and Y axis. In this example those properties are binded with the properties xMin, xMax, yMin, yMax of the ChartModel. Yo can also set them with constant or with javascript expressions.
Below an update of the chartModel.cpp file that rescale the ChartView to the 5 last values of the model
#include "chartmodel.h" ChartModel::ChartModel(QObject *parent) : QAbstractTableModel(parent) { m_xMin = 0.; m_xMax = 1.; m_yMin = 0.; m_yMax = 1.; } int ChartModel::rowCount(const QModelIndex & /* parent */) const { return vec_.size(); } int ChartModel::columnCount(const QModelIndex & /* parent */) const { return 2; } QVariant ChartModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); if (index.column() == 0){ return vec_.at(index.row()).first; } if (index.column() == 1){ return vec_.at(index.row()).second; } return QVariant(); } double ChartModel::get_xMin() const { return m_xMin; } double ChartModel::get_xMax() const { return m_xMax; } double ChartModel::get_yMin() const { return m_yMin; } double ChartModel::get_yMax() const { return m_yMax; } bool ChartModel::set_xMin(double val) { bool ret = false; if ((ret = (m_xMin != val))) { m_xMin = val; emit xMinChanged (m_xMin); } return ret; } bool ChartModel::set_xMax(double val) { bool ret = false; if ((ret = (m_xMax != val))) { m_xMax = val; emit xMaxChanged (m_xMax); } return ret; } bool ChartModel::set_yMin(double val) { bool ret = false; if ((ret = (m_yMin != val))) { m_yMin = val; emit yMinChanged (m_yMin); } return ret; } bool ChartModel::set_yMax(double val) { bool ret = false; if ((ret = (m_yMax != val))) { m_yMax = val; emit yMaxChanged (m_yMax); } return ret; } void ChartModel::appendData() { int const nbData = 1+qRound(10.*double(qrand())/double(RAND_MAX)); int const vecSize = vec_.size(); // if (!vecSize){ m_xMin = qInf(); m_xMax = -qInf(); m_yMin = qInf(); m_yMax = -qInf(); // } beginInsertRows(QModelIndex (), vecSize, vecSize+nbData); for(int seed = 0 ; seed < nbData; ++seed){ double const xVal = vec_.size(); double const yVal = double(qrand())/double(RAND_MAX); // set_xMin(qMin(m_xMin, xVal)); // set_xMax(qMax(m_xMax, xVal)); // set_yMin(qMin(m_yMin, yVal)); // set_yMax(qMax(m_yMax, yVal)); vec_.append(qMakePair<double, double>(xVal, yVal)); } for(int seed = (vecSize < 5 ? 0:vecSize-5) ; seed < vecSize; ++seed){ double const xVal = vec_.at(seed).first; double const yVal = vec_.at(seed).second; set_xMin(qMin(m_xMin, xVal)); set_xMax(qMax(m_xMax, xVal)); set_yMin(qMin(m_yMin, yVal)); set_yMax(qMax(m_yMax, yVal)); } endInsertRows(); }
-
@Winz said in Can someone provide a working example of VXYModelMapper with lineseries chart ?:
n also set them with con
Thanks so much
-
@Winz I tried to run the same example that you shared here - both the original and updated cpp code, and everytime I click on the graph the app crashes with a segfault. I am using Qt 5.12.0
Trace -received signal SIGSEGV, Segmentation fault.
0x00007fffecb6d91f in QString::operator=(QString const&) () from /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
(gdb) bt
#0 0x00007fffecb6d91f in QString::operator=(QString const&) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#1 0x00007fff9adcd09d in QtCharts::VerticalAxis::updateGeometry() [clone .part.37] [clone .constprop.39] () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Charts.so.5
#2 0x00007fff9add2e14 in QtCharts::ChartValueAxisY::updateGeometry() () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Charts.so.5
#3 0x00007fff9adae7d2 in QtCharts::AxisAnimation::updateCurrentValue(QVariant const&) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Charts.so.5
#4 0x00007fffecad2e10 in QVariantAnimationPrivate::setCurrentValueForProgress(double) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#5 0x00007fffecad3395 in QVariantAnimationPrivate::recalculateCurrentInterval(bool) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#6 0x00007fffecacf8ef in QAbstractAnimation::setCurrentTime(int) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#7 0x00007fffecad15a5 in QAbstractAnimation::start(QAbstractAnimation::DeletionPolicy) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#8 0x00007fffecce0581 in QObject::event(QEvent*) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#9 0x00007fffedb5785c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Widgets.so.5
#10 0x00007fffedb5e9f0 in QApplication::notify(QObject*, QEvent*) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Widgets.so.5
#11 0x00007fffeccb3c18 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#12 0x00007fffeccb6647 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#13 0x00007fffecd0b793 in postEventSourceDispatch(_GSource*, int ()(void), void*) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#14 0x00007fffe8ae1387 in g_main_context_dispatch () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#15 0x00007fffe8ae15c0 in () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#16 0x00007fffe8ae164c in g_main_context_iteration () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#17 0x00007fffecd0adcf in QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#18 0x00007fffeccb257a in QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#19 0x00007fffeccbaf80 in QCoreApplication::exec() () at /home/rahul.c/Qt5.12.0/5.12.0/gcc_64/lib/libQt5Core.so.5
#20 0x00005555555676fa in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at /home/rahul.c/code/dms_qt/src/main.cpp:26 -
@rahulch_pp Try to comment the line 18 of main.qml " animationOptions: ChartView.AllAnimations".
It seems to be buggy from Qt5.12 (and also Qt5.12.1)