Hyn*_*rix 8 c++ qt qml qt5 qt5.4
我有一个全局单例"设置",它保存应用程序设置.当我尝试运行以下代码时,我得到一个QML CheckBox: Binding loop detected for property "checked"
:
CheckBox {
checked: Settings.someSetting
onCheckedChanged: {
Settings.someSetting = checked;
}
}
Run Code Online (Sandbox Code Playgroud)
很明显为什么会出现这种错误,但是如何在没有绑定循环的情况下正确实现此功能呢?例如,我想在设置单例中保存复选框的当前选中状态.
我正在使用Qt 5.4和Qml Quick 2.
问候,
mcc*_*chu 16
不要绑它.因为复选框不完全依赖Setting.someSetting
.
当用户单击该复选框时,它CheckBox.checked
会自行更改.同时,属性绑定不再有效.Settings.someSetting
用户点击后无法修改CheckBox.因此,checked: Settings.someSetting
绑定是错误的.
如果要在组件准备就绪时为复选框分配初始值,请使用Component.onCompleted
以指定它:
CheckBox {
id: someSettingCheckBox
Component.onCompleted: checked = Settings.someSetting
onCheckedChanged: Settings.someSetting = checked;
}
Run Code Online (Sandbox Code Playgroud)
如果您正在处理更复杂的场景,则Setting.someSetting
可能会在运行时更改其他一些内容,并且需要同时更改复选框的状态.捕获onSomeSettingChanged
信号并明确更改复选框.值提交someSettingCheckBox
到Settings
只有当程序/插件/对话框/ XXX完成.
CheckBox { id: someSettingCheckBox }
//within the Settings, or Connection, or somewhere that can get the signal.
onSomeSettingChanged: someSettingCheckBox.checked = someSetting
Run Code Online (Sandbox Code Playgroud)
// Within the model
Q_PROPERTY(bool someSetting READ getSomeSetting WRITE setSomeSetting NOTIFY someSettingChanged)
void SettingsModel::setSomeSetting(bool checkValue) {
if (m_checkValue != checkValue) {
m_checkValue = checkValue;
emit someSettingChanged();
}
}
// QML
CheckBox {
checked: Settings.someSetting
onCheckedChanged: Settings.someSetting = checked
}
Run Code Online (Sandbox Code Playgroud)
诀窍是您emit
在模型中使用 if 检查来保护它。这意味着您仍然会得到一个绑定循环,但只有一个循环,而不是无限循环。当检查返回 false 时它停止,从而不发出继续循环。此解决方案非常干净,您不会收到警告,但您仍然可以获得绑定的所有好处。
CheckBox {
Component.onCompleted: checked = Settings.someSetting
onCheckedChanged: Settings.someSetting = checked;
}
Run Code Online (Sandbox Code Playgroud)
在此解决方案中,您将失去绑定。它只能在创建时具有默认设置并由用户更改。如果您扩展您的程序,以便其他事物更改您模型中的值,则此特定视图将无法反映这些更改。
Settings {
id: mySettings
onSomeSettingChanged: checkBox.checked = someSetting
}
CheckBox {
id: checkBox
onCheckedChanged: mySettings.someSetting = checked
}
Run Code Online (Sandbox Code Playgroud)
提到此解决方案是为了解决这些问题,但从未写出。它在功能上是完整的。模型变化体现出来,用户可以改变数据,没有绑定就没有绑定循环;只有两个离散的任务。(x: y
是绑定,x = y
是赋值)
这有几个问题。首先是我认为它丑陋和不雅,但这可以说是主观的。在这里看起来不错,但是如果您在此视图中有一个代表 10 个事物的模型,这将变成信号意大利面。更大的问题是它不适用于委托,因为它们仅按需存在。
例子:
MyModel {
id: myModel
// How are you going to set the check box of a specific delegate when
// the model is changed from here?
}
ListView {
id: listView
model: myModel.namesAndChecks
delegate: CheckDelegate {
id: checkDelegate
text: modelData.name
onCheckStateChanged: modelData.checkStatus = checked
}
}
Run Code Online (Sandbox Code Playgroud)
你实际上可以做到。我已经编写了自定义 QML 信号和连接来执行此操作,但是代码的复杂性让我想投掷,更糟糕的是,您可能会在不需要时强制创建委托。
例如,如果您不想进行绑定循环 - 不进行绑定,请使用代理变量。其他简单的解决方案可以是检查值:
CheckBox {
checked: Settings.someSetting
onCheckedChanged: {
if (checked !== Settings.someSetting) {
Settings.someSetting = checked;
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
您还可以进行双向绑定来解决此问题:
CheckBox {
id: checkBox
Binding { target: checkBox; property: "checked"; value: Settings.someSetting }
Binding { target: Settings; property: "someSetting"; value: checkBox.checked }
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
12333 次 |
最近记录: |