Reputation: 97
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 for page 1
are still taking place, even though visible
is set to false
on page 1
. I wish to have QML respond to binding updates, only when the page is visible
, as it would improve performance.
I have tried using the Binding
element as described here: Binding QML Type and here: Prevent QML Property Bindings when QML object isn't visible?, 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 activated
property.
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_H
sensordata.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
}
Upvotes: 0
Views: 881
Reputation: 4208
Indeed it seems the Binding
is still evaluating the value
property, but just not assigning it to the text
property when the when
clause is false. I would consider this buggy, but maybe there is a rationale behind it.
The solution is to use a State
as in the following code. This also gives the possibility to state that the value is not being read currently.
Rectangle{
x: 280
y: 20
width:200
height:150
color:"red"
Text {
id: readout
y: 76
width: 85
height: 67
text: {
console.log("new value"); //does not print when deactivated
sensorData.sensorReading.toFixed(1)
}
states: [
State {
name: "deactivated"
when: !controlRect.activated
PropertyChanges {
target: readout
text: "off"
}
}
]
}
}
Upvotes: 1