property binding on object chain
-
Hi!
I am trying to have a
Textget the value of a property of a C++ object that can sometimes be null.I have 2 C++ objects:
Project:
class Project : public QObject { Q_OBJECT Q_PROPERTY(Parameters* parameters READ parameters NOTIFY parametersChanged) /* definintion of parameters getter/setter/signal. The setter emits the parametersChanged signal */ };Parameters:
class Parameters: public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) /* definintion of name getter/setter/signal. The setter emits the nameChanged signal */ };Now, in my QML, I have:
Text { text: myProject.parameters.name }But this does not work. The name is never filled because my project starts with its
parametersproperty set to null. When the property is filled, QML registers it, but after that, if name changes, nothing is happening in QML.I tried:
Text { text: myProject.parameters ? myProject.parameters.name : '' Connections { target: myProject: onParametersChanged: { console.log('parameters changed') } // emitted and received } }My question being: Is there a way to force the binding to be reprocessed entirely when
parameterschanges so that it will detect that sinceparameterschanged,parameters.nameneeds to be "re-binded" ?Thanks !
-
Hi!
I am trying to have a
Textget the value of a property of a C++ object that can sometimes be null.I have 2 C++ objects:
Project:
class Project : public QObject { Q_OBJECT Q_PROPERTY(Parameters* parameters READ parameters NOTIFY parametersChanged) /* definintion of parameters getter/setter/signal. The setter emits the parametersChanged signal */ };Parameters:
class Parameters: public QObject { Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) /* definintion of name getter/setter/signal. The setter emits the nameChanged signal */ };Now, in my QML, I have:
Text { text: myProject.parameters.name }But this does not work. The name is never filled because my project starts with its
parametersproperty set to null. When the property is filled, QML registers it, but after that, if name changes, nothing is happening in QML.I tried:
Text { text: myProject.parameters ? myProject.parameters.name : '' Connections { target: myProject: onParametersChanged: { console.log('parameters changed') } // emitted and received } }My question being: Is there a way to force the binding to be reprocessed entirely when
parameterschanges so that it will detect that sinceparameterschanged,parameters.nameneeds to be "re-binded" ?Thanks !
@ebatsin said in property binding on object chain:
"nested" properties do not emit such a binding, you could try a Binding elementText { id: t Binding { when: myProject.parameters value: myProject.parameters.name target: t property: "text" } }(untested)
-
@raven-worx
Thanks, this works in the case I explained previously (depth 2 nesting) but I get an error at thevalueline of the binding in QML (even though it works):
TypeError: Cannot read property 'name' of nullBut is there a way that would be robust to something like that:
project.parameters.angles.rollwhere bothparametersandanglescould be null be null ?Since I can't do:
Text { id: t Binding { when: project.parameters.angles // do not work when parameters is null .... } }This is more of a theorical question since I do not expect this problem to happen in my use case.
Also, is there somewhere documentation/blog post/article that explains why nested properties bindings are not re-evaluated if one part of the nested chains changes (ie:parametersgoes fromnullto a valid pointer) ?@fcarney
The signals are explicitly emitted when the value is changed:void Project::setParameters(Parameters* parameters) { if(d->parameters != parameters) { d->parameters = parameters; emit parametersChanged(); } }void Parameters::setName(QString const& name) { if(d->name != name) { d->name = name; emit nameChanged(); } }The values are changed exclusively from C++ (controlled by a
QStateMachine)Thanks for your help :)
-
@raven-worx
Thanks, this works in the case I explained previously (depth 2 nesting) but I get an error at thevalueline of the binding in QML (even though it works):
TypeError: Cannot read property 'name' of nullBut is there a way that would be robust to something like that:
project.parameters.angles.rollwhere bothparametersandanglescould be null be null ?Since I can't do:
Text { id: t Binding { when: project.parameters.angles // do not work when parameters is null .... } }This is more of a theorical question since I do not expect this problem to happen in my use case.
Also, is there somewhere documentation/blog post/article that explains why nested properties bindings are not re-evaluated if one part of the nested chains changes (ie:parametersgoes fromnullto a valid pointer) ?@fcarney
The signals are explicitly emitted when the value is changed:void Project::setParameters(Parameters* parameters) { if(d->parameters != parameters) { d->parameters = parameters; emit parametersChanged(); } }void Parameters::setName(QString const& name) { if(d->name != name) { d->name = name; emit nameChanged(); } }The values are changed exclusively from C++ (controlled by a
QStateMachine)Thanks for your help :)
@ebatsin said in property binding on object chain:
But is there a way that would be robust to something like that: project.parameters.angles.roll where both parameters and angles could be null be null ?
Since I can't do:
Text {
id: t
Binding {
when: project.parameters.angles // do not work when parameters is null
....
}
}Binding { when: project.parameters && project.parameters.angles } -
@ebatsin said in property binding on object chain:
But is there a way that would be robust to something like that: project.parameters.angles.roll where both parameters and angles could be null be null ?
Since I can't do:
Text {
id: t
Binding {
when: project.parameters.angles // do not work when parameters is null
....
}
}Binding { when: project.parameters && project.parameters.angles }@raven-worx Indeed. Should have found that one alone :/
I still get an error when the QML is parsed which is not really sexy in my application logs (but the binding works so I'll call it a win for now).
As I said before, is there somewhere that explains why nested bindings are not re-evaluated if a property in the middle of the chain changes ?
-
@raven-worx Indeed. Should have found that one alone :/
I still get an error when the QML is parsed which is not really sexy in my application logs (but the binding works so I'll call it a win for now).
As I said before, is there somewhere that explains why nested bindings are not re-evaluated if a property in the middle of the chain changes ?
@ebatsin said in property binding on object chain:
As I said before, is there somewhere that explains why nested bindings are not re-evaluated if a property in the middle of the chain changes ?
i am not aware of an explaination of this behavior.
But i am thinking of the following:
A triggering of the the parent property might notify other bindings even if actually nothing has changed for that particular binding -
You could just do :
Text { text: myProject.parameters && myProject.parameters.name || "" }Nested properties ARE re-evaluated if a property in the middle of the chain changes.
-
You could just do :
Text { text: myProject.parameters && myProject.parameters.name || "" }Nested properties ARE re-evaluated if a property in the middle of the chain changes.
@GrecKo This won't work. Although changing
parameterswill make thetextto be re-eavaluted, changing of the nested propertynamewon't trigger thetextto be re-evaluated. It is because initially the expression bind to thenameproperty of the oldparametersinstance.