Qt 5.4/ Qml: предотвращение цикла привязки

у меня есть глобальные одноэлементные "настройки", которые содержат настройки приложения. Когда я пытаюсь запустить следующий код, я получаю QML CheckBox: Binding loop detected for property "checked":

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

очевидно, почему эта ошибка возникает, но как я могу правильно реализовать эту функцию без привязки петли? Например. Я хочу сохранить текущее проверенное состояние флажка в настройках singleton.

Я использую Qt 5.4 и QML Quick 2.

С уважением,

4 ответов


не связывайте его. Потому что флажок не полностью зависит от Setting.someSetting.

когда пользователь щелкнул флажок,CheckBox.checked изменяется сам по себе. В то же время привязка свойства больше не является допустимой. Settings.someSetting не удается изменить флажок после нажатия пользователем. Следовательно,checked: Settings.someSetting привязка неправильная.

если вы хотите присвоить начальное значение флажка, когда компонент будет готов, используйте Component.onCompleted, чтобы назначить его:

CheckBox {
    id: someSettingCheckBox 

    Component.onCompleted: checked = Settings.someSetting
    onCheckedChanged: Settings.someSetting = checked; 
}

если вы работаете над более сложным сценарием, то Setting.someSetting могут быть изменены некоторыми другими вещами во время выполнения, и состояние флажка необходимо изменить одновременно. Лови onSomeSettingChanged сигнал и явно изменил флажок. Отправить значение someSettingCheckBox to Settings только после завершения программы/виджета/диалога/xxx.

CheckBox { id: someSettingCheckBox }

//within the Settings, or Connection, or somewhere that can get the signal.
onSomeSettingChanged: someSettingCheckBox.checked = someSetting

Если вы не хотите делать цикл привязки - не делайте привязку, используйте переменную прокси, например. Другим простым решением может быть проверка значения:

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

вы также можете сделать двустороннюю привязку для решения этой проблемы:

CheckBox {
    id: checkBox

    Binding { target: checkBox; property: "checked"; value: Settings.someSetting }
    Binding { target: Settings; property: "someSetting"; value: checkBox.checked }
}

иногда полезно разделить входные и выходные значения в элементе управления. В этом случае элемент управления всегда отображает реальное значение, а также может отображать задержку для пользователя.

CheckBox {
    checked: Settings.someSetting
    onClicked: Settings.someSetting = !checked
}