Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Changing the content of a QVector in a C++ model doesn’t trigger the QML bindings between the model and the custom C++ component used as a delegate



  • Good Morning,

    Here is my problem: Changing the content of a QVector in a C++ model doesn’t trigger the QML bindings between the model and the custom C++ component used as a delegate

    I’ve got a QVector in my C++ model. I’ve got a C++ custom component based on a QQuickPaintedItem.
    Adding a value in the vector of the model doesn’t trigger the bindings between the model and the component.

    Context :

    I’m trying to draw the successive results from a measurement instrument.
    This makes a curve displayed with a QQuickPaintedItem.

    I’ve got a « VolmeterChannel » class, in which I’m defining a « results » property that is accessible to the QML.
    (NB : my Voltmeter class has two channels, managed by two member classes VoltmeterChannel).

    Class VoltmeterChannel : public QObject {
        Q_OBJECT
        …
        Q_PROPERTY (QVector<QPointF> results READ get_results WRITE set_results NOTIFY resultsChanged)
        …
        QVector<QPoint> m_results ;
        …
    }
    

    Every time I get a result from the Voltmeter, I’m adding the last measurement to my result vector :

    void VoltmeterChannel::setResult(int channel, qreal result) {
        static int x=0;        
        if (m_results.count() >= NB_SAMPLES)
            m_results.removeLast();
        m_results(QPointF(x, result));
        set_results(m_results);
        ++x;
        emit resultsChanged(m_results);
    }
    

    The QML bindings are as follow :

                        Repeater {
                            model: [
                                Global.voltmeter.channel1,
                                Global.voltmeter.channel2,
                            ];
                            delegate: PaintedGraph {
                                id: _graph;
                                xMin: _graph.object.xMin;
                                xMax: _graph.object.xMax;
                                yMin: _graph.object.yMin;
                                yMax: _graph.object.yMax;
                                points: _graph.object.results;
                                visible: _graph.object.selected;
                                color: {
                                    switch (_graph.object.number) {
                                    case VoltmeterSelection.CHANNEL_1: return "#FEDB00";
                                    case VoltmeterSelection.CHANNEL_2: return "#001489";
                                    }
                                    return "gray";
                                }
                                anchors {
                                    fill: parent;
                                    topMargin: Global.theme.spaceM;
                                    leftMargin: 2;
                                    rightMargin: 2;
                                    bottomMargin: Global.theme.spaceM;
                                }
    
                                readonly property VoltmeterChannel object: modelData;
                            }
                        }
    

    I found a « quick and dirty » fix to that problem, by reconstructing a whole QVector every time and using setResults(results).

    Then, the QML bindings are triggered and the curve is drawn.
    This is working but I don’t want to copy twice every value from the QVector every time I get a new result, as this is very bad coding…

    So, how could I program this so that adding a new value in the QVector will be signaled to the QQuickPaintedItem so it will continue drawing the curve?


  • Moderators

    @JL-SABATIER said in Changing the content of a QVector in a C++ model doesn’t trigger the QML bindings between the model and the custom C++ component used as a delegate:

    Adding a value in the vector of the model doesn’t trigger the bindings between the model and the component.

    That is expected.

    The QML bindings are not triggered by modifying a variable. The QML bindings are triggered by the NOTIFY signal.

    how could I program this so that adding a new value in the QVector will be signaled to the QQuickPaintedItem so it will continue drawing the curve?

    Emit your resultsChanged() signal every time a new value is added.



  • Thanks for your reply and for pointing me out where to look for the bug.
    I was trying to emit the signal, but there was a bug in the code. Which is now fixed. Thanks again.


  • Moderators

    @JL-SABATIER You're most welcome. Happy coding!


Log in to reply