Solved Property assignments from JavaScript signal handling
-
I have a situation where I have a group of buttons acting as a kind of toolbar for a component. There are some slightly tricky dependencies between the buttons (eg one button might activate a mode in which other buttons are enabled or disabled) as well dependencies in the component itself on what has been selected via the buttons.
All these dependencies are expressed in terms of declarative property bindings in the usual QML manner.
What I am feeling uneasy about is that this is all being driven by property assignments in
Button.onClicked
handlers. My understanding, which is probably incomplete, is that assignments in JS can lead to property bindings being broken, though in fact I haven't seen any issues yet.Can anyone clarify the rules about what can and can't be relied upon? If I should avoid doing this, what would be the approach recommended instead?
-
Hi @Bob64,
You need to use
Qt.binding()
for that:here is an example from Creating Property Bindings from JavaScript
import QtQuick 2.0 Rectangle { width: 100 height: width * 2 focus: true Keys.onSpacePressed: { height = Qt.binding(function() { return width * 3 }) } }
-
@Gojir4 Thanks. I think this has helped to clarify the issue for me. In my case I am simply assigning boolean values to properties in my
onClicked
handlers. These properties never had a binding to other properties so the assignment of the new value does not break any binding. Now, there are property bindings elsewhere that are dependent on the properties that I am assigning but these changes are propagated OK as far as I can see, and I now think that this is what we would expect. -
@Bob64 Glad it helps.
Please don't forget to set the post as solved if this answer to your question
Thanks! -
My rule of thumb is to act on data, not directly UI objects.
In your case it would mean that instead of doing something like this:
Row { Button { text: "Change mode" onClicked: { fooButton.enabled = !fooButton.enabled barButton.enabled = !barButton.enabled } } Button { id: fooButton text: "Foo" enabled: true onClicked: doFoo() } Button { id: barButton text: "Bar" enabled: false onClicked: doBar() } }
You'll do the following:
Row { id: buttonRow property bool myMode: true Button { text: "Change mode" onClicked: buttonRow.myMode = !buttonRow.myMode } Button { text: "Foo" enabled: buttonRow.myMode onClicked: doFoo() } Button { text: "Bar" enabled: !buttonRow.myMode onClicked: doBar() } }
Does that help?
-
@GrecKo Thank you. That is a useful point to make and is in fact very close to the sort of thing I am doing.
I think my problem had been that I had missed the point about what the potential issue actually is in JS property assignments. I had it in my head that it was something to avoid when there are bindings dependent on the property being set, but really it's only an issue if existing bindings are being broken by the assignment. I hadn't been forced to think about it properly because all of the bindings I had relied upon so far either depended on properties provided by QML itself or on properties I am providing from my C++ backend objects. And in the places I was already setting properties directly in JS, I was not worried about them because they were typically for 'one-shot' uses - e.g. setting something on a dialog or a popup menu just before showing it.
-
@Bob64 I see that you've received the clarifications you need for this particular issue.
If you'd like to further your understanding, see this article: https://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html