Suppose I have a custom CheckBox
:
//MyCheckBox.qml
CheckBox {
required property QtObject proxy
checked: proxy.value
Binding {
target: proxy
property: "value"
value: checked
}
}
So the checked status of the MyCheckBox
bound to the value
property of my object (proxy
) and vise-versa, i.e. I have a two-way binding.
I am using my custom checkbox as follows:
//My window
Item {
...
MyCheckBox {
id: ordinaryCheck
proxy: ...
}
...
}
Everything works as expected. But what if I need to invert the logic for some instance of MyCheckBox
: when proxy.value
is true the checkbox is unchecked, and when proxy.value
is false the checkbox is checked ? But this, ofc, doesn't work as I have a binding loop here if I try to do this:
Item {
...
MyCheckBox {
id: invertedCheck
proxy: ...
checked: !proxy.value
Binding {
target: proxy.value
property: "value"
value: !checked
}
}
The Qt bindings are also not an option:
//MyCheckBox.qml
CheckBox {
required property QtObject proxy
checked: proxy.value
Component.onCompleted {
property.value = Qt.binding(function() { return checked });
}
}
I have the same binding loop error in this case.
So what is my option to reach the goal, how to alternate the binding at the moment of instantiation ?
CodePudding user response:
If you're concerned about a potential binding loop, it is a potential candidate to rewrite it as an imperative implementation, e.g.
CheckBox {
required property QtObject proxy
onCheckedChanged: {
if (proxy && proxy.value !== checked) {
proxy.value = checked;
}
}
property bool proxyValue: proxy && proxy.value ? true : false
onProxyValueChanged: {
if (checked !== proxyValue) {
checked = proxyValue;
}
}
}
CodePudding user response:
Your first version might also technically be a binding loop but is not detected as such.
You want to bind your checkbox value to your proxy value, and when the user toggles the checkbox you want to modify the proxy value.
To avoid binding loops, use specific interaction signals for each component, not generic onChanged signal. The former will fire only when the user interact with the UI, the latter will fire every time, even when the changes come from a backend change, leading to a potential binding loop.
In your case you want the toggled
signal:
//MyCheckBox.qml
CheckBox {
required property QtObject proxy
checked: proxy.value
onToggled: proxy.value = checked
}
Note that this only works with QQC2 since they are not breaking the checked: proxy.value
binding when the user toggles the checkbox, but still change the checked
property value, hoping for an eventual resolution.