Qt 5.4 / Qml: disable binding loop

I have a global singleton "Settings", which contains the application settings. When I try to run the following code, I get a QML CheckBox: Binding loop detected for property "checked" :

 CheckBox { checked: Settings.someSetting onCheckedChanged: { Settings.someSetting = checked; } } 

Obviously, why this error occurs, but how can I correctly implement this functionality without binding? For instance. I want to keep the current state of the checkbox in singleton settings.

I am using Qt 5.4 and Qml Quick 2.

Hello,

+6
source share
4 answers

Do not bind it. Because the checkbox is not completely dependent on Setting.someSetting .

When the user clicked the checkbox, CheckBox.checked will be changed on its own. At the same time, property bindings are no longer valid. Settings.someSetting cannot change CheckBox after user click. Therefore, the checked: Settings.someSetting binding is incorrect.

If you want to assign an initial value to the flag when the component is ready, use Component.onCompleted to assign it:

 CheckBox { id: someSettingCheckBox Component.onCompleted: checked = Settings.someSetting onCheckedChanged: Settings.someSetting = checked; } 

If you are working on a more complex scenario, Setting.someSetting can be changed by other things at runtime, and the state of this field must be changed at the same time. Catch the onSomeSettingChanged signal and explicitly change the flag. Send the value of someSettingCheckBox to Settings only after the program / widget / dialog / xxx is completed.

 CheckBox { id: someSettingCheckBox } //within the Settings, or Connection, or somewhere that can get the signal. onSomeSettingChanged: someSettingCheckBox.checked = someSetting 
+10
source

If you do not want to create a binding cycle - do not make bindings, use, for example, a proxy variable. Another simple solution would be to check the value:

 CheckBox { checked: Settings.someSetting onCheckedChanged: { if (checked !== Settings.someSetting) { Settings.someSetting = checked; } } } 
+4
source

You can also do two-way binding to solve this problem:

 CheckBox { id: checkBox Binding { target: checkBox; property: "checked"; value: Settings.someSetting } Binding { target: Settings; property: "someSetting"; value: checkBox.checked } } 
+3
source

It is sometimes useful to separate input and output values ​​in a control. In this case, the control always displays the real value, and can also show the delay to the user.

 CheckBox { checked: Settings.someSetting onClicked: Settings.someSetting = !checked } 
+1
source

Source: https://habr.com/ru/post/981801/


All Articles