Bidirectional binding properties between QML and Cpp
-
Hi,
I have a GUI element (e.g. switch) whose state is binded to some Cpp objects property and vice versa, e.g.:window.qml: MySwitch { state: myCppObject.property onStateChanged: myCppObject.property = state } MySwitch.qml: Item { property bool state MouseArea { onCLicked: state= !state } Rectangle { color: state ? "black" : white } }
My implementation (the code above) has one problem. When user clicks the switch ( onCLicked: state = !state is executed) then setting value of the switch from backend stops working (because binding state: myCppObject.property now doesn't exist - at least I think so).
What is the "nicest" way to make bidirectional bindings?
-
@MartinD hi,
MySwitch { state: myCppObject.property // onStateChanged: myCppObject.property = state No need this } Item { property bool state MouseArea { onClicked : { myCppObject.property = !myCppObject.property } // onCLicked: state= !state //do this to your cpp object directly so the QML will follow .. } Rectangle { color: state ? "black" : white } }
-
I tried same thing with QML CheckBox:
CheckBox { text: "CheckBox" checked: cppObject.property onCheckedChanged: cppObject.property = checked }
And again, this doesn't work - checkbox is checked and once something else other than checkbox changes cppObject.property to false, checkbox remains checked.
How to make bidirectional binding for this checkbox? Pleae also consider that cppObjet can be set to null sometimes and when it is set to valid object checked property of checkbox must be also correctly reevaluated.
-
I think in this case, you'll have to forgo binding.
MySwitch { id: sSwitch state: myCppObject.property //Now only the initial state during construction onStateChanged: myCppObject.property = state Connections{ target: myCppObject onPropertyChanged: sSwitch.state = property } }
-
Another way to do it would be to reassign the binding after:
MySwitch { id: sSwitch state: myCppObject.property onStateChanged: { myCppObject.property = state; state = Qt.binding(() => myCppObject.property); } }
Qt Quick Controls 2 do some magic in c++ so that you don't have to rebind. Using a QQC2.Switch and just customizing its appareance would be a solution too.
-
@J.Hilk Thanks, that will almost work. But it can also happen that myCppObject can be set to null (during that the switch is not valid and e.g. should not be visible to the user) and then myCppObject is set to a valid instance. If myCppObject.property and switch state holds different values then the switch will be in incorrect state. So it seems that I have to write another piece of code to deal with this.
Really, is it so difficult in QML to make bidirectional binding? Isn't there any better way?