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 data

    main.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()
                }
            }
        }
    }
    
    


  • @Winz for the brilliant example you mentioned, I see the chart is compressing the graph, If I want to let the screen move to display only the last 5 points, what I need to change!?



  • 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 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)



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.