Update Q_PROPERTY: how does the notify signal work?
-
Hi,
I have a c++ class, which exposes a QList<QObject*> as a model and also has a int property:
Q_PROPERTY(QVariant customModel READ getModel NOTIFY customModelChanged) Q_PROPERTY(int currentValue READ getCurrentValue NOTIFY customModelChanged)
customModelChanged gets emitted whenever the model is changed. In qml I have a property set to currentValue, however, I can see (having a breakpoint in getCurrentValue during debugging) that getCurrentValue is not called when customModelChanged is emitted. Do I missunderstand somethinbg?
-
Hi,
I have a c++ class, which exposes a QList<QObject*> as a model and also has a int property:
Q_PROPERTY(QVariant customModel READ getModel NOTIFY customModelChanged) Q_PROPERTY(int currentValue READ getCurrentValue NOTIFY customModelChanged)
customModelChanged gets emitted whenever the model is changed. In qml I have a property set to currentValue, however, I can see (having a breakpoint in getCurrentValue during debugging) that getCurrentValue is not called when customModelChanged is emitted. Do I missunderstand somethinbg?
Hi,
getCurrentValue is not supposed to be called when currentValueChanged is emited
You generally use getCurrentValue from qml side to get the value of a private property (like accessor)
class MachineBackend : public QObject { Q_OBJECT public: Q_PROPERTY(QString message READ getMessage WRITE setMessage NOTIFY messageChanged) QString getMessage(){ return m_message; } void setMessage(QString newMessage){ m_message=newMessage; emit messageChanged() // Will notify en ensure value is refreshed } private : QString m_message;
then in qml :
Text{
text : myObj.getMessage // will refresh
text : myObj.message
} -
in addition to previous post, you should always follow <propertyName> and propertyNameChanged signal.
-
Hi,
getCurrentValue is not supposed to be called when currentValueChanged is emited
You generally use getCurrentValue from qml side to get the value of a private property (like accessor)
class MachineBackend : public QObject { Q_OBJECT public: Q_PROPERTY(QString message READ getMessage WRITE setMessage NOTIFY messageChanged) QString getMessage(){ return m_message; } void setMessage(QString newMessage){ m_message=newMessage; emit messageChanged() // Will notify en ensure value is refreshed } private : QString m_message;
then in qml :
Text{
text : myObj.getMessage // will refresh
text : myObj.message
}Hi,
Some small yet useful improvements:
void setMessage(const QString& newMessage){ // const reference avoids useless copies if (m_message == newMessage) // Don't notify if the value doesn't change return; m_message=newMessage; emit messageChanged(m_message) // Send the changed value further }
-
Hi,
getCurrentValue is not supposed to be called when currentValueChanged is emited
You generally use getCurrentValue from qml side to get the value of a private property (like accessor)
class MachineBackend : public QObject { Q_OBJECT public: Q_PROPERTY(QString message READ getMessage WRITE setMessage NOTIFY messageChanged) QString getMessage(){ return m_message; } void setMessage(QString newMessage){ m_message=newMessage; emit messageChanged() // Will notify en ensure value is refreshed } private : QString m_message;
then in qml :
Text{
text : myObj.getMessage // will refresh
text : myObj.message
}@LeLev said in Update Q_PROPERTY: how does the notify signal work?:
getCurrentValue is not supposed to be called when currentValueChanged is emited
OP doesn't have a currentValueChanged signal.
You generally use getCurrentValue from qml side to get the value of a private property (like accessor)
No, you generally use
currentValue
from qml, you shouldn't call getters directly. And it won't work in your example sincegetMessage
is not invokable (that's a good thing). -
@LeLev said in Update Q_PROPERTY: how does the notify signal work?:
getCurrentValue is not supposed to be called when currentValueChanged is emited
OP doesn't have a currentValueChanged signal.
You generally use getCurrentValue from qml side to get the value of a private property (like accessor)
No, you generally use
currentValue
from qml, you shouldn't call getters directly. And it won't work in your example sincegetMessage
is not invokable (that's a good thing). -
Hi,
getCurrentValue is not supposed to be called when currentValueChanged is emited
You generally use getCurrentValue from qml side to get the value of a private property (like accessor)
class MachineBackend : public QObject { Q_OBJECT public: Q_PROPERTY(QString message READ getMessage WRITE setMessage NOTIFY messageChanged) QString getMessage(){ return m_message; } void setMessage(QString newMessage){ m_message=newMessage; emit messageChanged() // Will notify en ensure value is refreshed } private : QString m_message;
then in qml :
Text{
text : myObj.getMessage // will refresh
text : myObj.message
}@LeLev said in Update Q_PROPERTY: how does the notify signal work?:
getCurrentValue is not supposed to be called when currentValueChanged is emited
as far as I know, that is exactly what is happening, the as
READ
marked function is called from the QML side, as soon as you emit the currentValueChanged signal.
But that is happening automaticaly in the background, all part of the Q_PROPERTY macro, if you want to call the getter manually, you will have to mark it as Q_INVOKABLE -
-
Then make it a separate signal and connect explicitly to that one.
A notify signal is associated to one property (single responsibility paradigm). Since you want a catch all signal, it should be a clear separated element. This will have the added values of making your code cleaner, clearer and avoid maintenance hell.
-
In addition to what @SGaist said, if you use same signal for every properties, property binding for those properties will not work. Also you will breaking declarative flow. It will be confusing and confused code. Better avoid it.
-
Hi,
Some small yet useful improvements:
void setMessage(const QString& newMessage){ // const reference avoids useless copies if (m_message == newMessage) // Don't notify if the value doesn't change return; m_message=newMessage; emit messageChanged(m_message) // Send the changed value further }
@SGaist said in Update Q_PROPERTY: how does the notify signal work?:
emit messageChanged(m_message)
I often see that the notify signal of a
Q_PROPERTY
is defined as an argument-lessvoid
method, i.e.emit messageChanged(()
Common sense tells me that providing an argument to the method avoids an unnecessary call to the READ getter method. If that is correct, why would one define argument-less notify signals?
-
You may have a property that requires some processing to retrieve (for example slow disk/network access) and you do not want to do that for every signal émission only when there's an actual need for the data.
-
And the QML engine doesn't event read the parameter of the notify signal if there's one.