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?
-
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?
@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. -
@JL-SABATIER You're most welcome. Happy coding!