How to conditionally disable QML Binding to C++ backend?
-
I am working on QML Application for an embedded system that has a lot of property bindings: many sensor data is displayed throughout different pages of the app. Only 1 page is visible at a time.
When I'm on
page 2, the property bindings forpage 1are still taking place, even thoughvisibleis set tofalseonpage 1. I wish to have QML respond to binding updates, only when the page isvisible, as it would improve performance.I have tried using the
Bindingelement as described here: Binding QML Type and here: https://stackoverflow.com/questions/32506359/prevent-qml-property-bindings-when-qml-object-isnt-visible?rq=1, but I've noticed that a binding will still update in QML.I am wondering if it is possible to completely eliminate the binding, if not on
page 1.My code for my attempt at using the Binding Element is attached below. Instead of multiple pages being visible/invisible, I've used a button that toggles a
activatedproperty.main.qml
Rectangle{ x: 280 y: 20 width:200 height:150 color:"red" Text { y: 76 width: 85 height: 67 text: "off" Binding on text { value: { // I am surprised to find this prints, regardless of value of controlRect.activated console.log("new value"); sensorData.sensorReading.toFixed(1) } when: controlRect.activated } } } Rectangle{ id: controlRect x: 20 y: 20 width:200 height:150 property bool activated: true color:{ if (controlRect.activated){ "green" } else{ "yellow" } } MouseArea { anchors.fill: parent onClicked: { console.log("State changed to",!parent.activated); parent.activated = !parent.activated } } }backend.cpp, instantiated in main.cpp
#include "backend.h" #include <QQmlContext> Backend::Backend(QQmlApplicationEngine* engine, QObject *parent) : QObject(parent) { sensorData = new SensorData(); QQmlContext* ctxt(engine->rootContext()); // Connecting back end object instances to front end ctxt->setContextProperty("sensorData", sensorData); }sensordata.h
#ifndef SENSORDATA_H #define SENSORDATA_H #include <QObject> #include <QTimer> class SensorData : public QObject { Q_OBJECT public: Q_PROPERTY(double sensorReading MEMBER m_sensorReading NOTIFY sensorReadingChanged) explicit SensorData(QObject *parent = nullptr); ~SensorData() {} private: double m_sensorReading; double temp; QTimer m_timer; signals: void sensorReadingChanged(); public slots: void slot_updateReading(); }; #endif // SENSORDATA_Hsensordata.cpp
#include "sensordata.h" #include <QDebug> SensorData::SensorData(QObject *parent) : QObject(parent) { // for simulating sensor data srand( (unsigned)time(NULL) ); m_timer.setInterval(100); m_timer.setSingleShot(false); QObject::connect(&m_timer, &QTimer::timeout, this, &SensorData::slot_updateReading); m_timer.start(); } // simulate my sensor data void SensorData::slot_updateReading(){ m_sensorReading = modf(rand() / 100000.0, &temp); emit sensorReadingChanged(); // emit for QML binding to update } -
I am working on QML Application for an embedded system that has a lot of property bindings: many sensor data is displayed throughout different pages of the app. Only 1 page is visible at a time.
When I'm on
page 2, the property bindings forpage 1are still taking place, even thoughvisibleis set tofalseonpage 1. I wish to have QML respond to binding updates, only when the page isvisible, as it would improve performance.I have tried using the
Bindingelement as described here: Binding QML Type and here: https://stackoverflow.com/questions/32506359/prevent-qml-property-bindings-when-qml-object-isnt-visible?rq=1, but I've noticed that a binding will still update in QML.I am wondering if it is possible to completely eliminate the binding, if not on
page 1.My code for my attempt at using the Binding Element is attached below. Instead of multiple pages being visible/invisible, I've used a button that toggles a
activatedproperty.main.qml
Rectangle{ x: 280 y: 20 width:200 height:150 color:"red" Text { y: 76 width: 85 height: 67 text: "off" Binding on text { value: { // I am surprised to find this prints, regardless of value of controlRect.activated console.log("new value"); sensorData.sensorReading.toFixed(1) } when: controlRect.activated } } } Rectangle{ id: controlRect x: 20 y: 20 width:200 height:150 property bool activated: true color:{ if (controlRect.activated){ "green" } else{ "yellow" } } MouseArea { anchors.fill: parent onClicked: { console.log("State changed to",!parent.activated); parent.activated = !parent.activated } } }backend.cpp, instantiated in main.cpp
#include "backend.h" #include <QQmlContext> Backend::Backend(QQmlApplicationEngine* engine, QObject *parent) : QObject(parent) { sensorData = new SensorData(); QQmlContext* ctxt(engine->rootContext()); // Connecting back end object instances to front end ctxt->setContextProperty("sensorData", sensorData); }sensordata.h
#ifndef SENSORDATA_H #define SENSORDATA_H #include <QObject> #include <QTimer> class SensorData : public QObject { Q_OBJECT public: Q_PROPERTY(double sensorReading MEMBER m_sensorReading NOTIFY sensorReadingChanged) explicit SensorData(QObject *parent = nullptr); ~SensorData() {} private: double m_sensorReading; double temp; QTimer m_timer; signals: void sensorReadingChanged(); public slots: void slot_updateReading(); }; #endif // SENSORDATA_Hsensordata.cpp
#include "sensordata.h" #include <QDebug> SensorData::SensorData(QObject *parent) : QObject(parent) { // for simulating sensor data srand( (unsigned)time(NULL) ); m_timer.setInterval(100); m_timer.setSingleShot(false); QObject::connect(&m_timer, &QTimer::timeout, this, &SensorData::slot_updateReading); m_timer.start(); } // simulate my sensor data void SensorData::slot_updateReading(){ m_sensorReading = modf(rand() / 100000.0, &temp); emit sensorReadingChanged(); // emit for QML binding to update }@HiddenNetwork
in all honesty, the best/proper way would be by using a Loader component to only load those files that you actually need/want to show.That would take care of the binding issue and increase even more the performance.