首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QT5.4/Qml:防止绑定循环

QT5.4/Qml:防止绑定循环
EN

Stack Overflow用户
提问于 2015-01-31 10:44:49
回答 5查看 19.1K关注 0票数 18

我有一个全局单例“设置”,它保存应用程序设置。当我尝试运行以下代码时,我会得到一个QML CheckBox: Binding loop detected for property "checked"

代码语言:javascript
复制
CheckBox {
    checked: Settings.someSetting                         
    onCheckedChanged: {
        Settings.someSetting = checked;
    }
}

这个错误发生的原因很明显,但是如果没有绑定循环,我如何才能正确地实现这个功能呢?例如,我希望将复选框的当前选中状态保存在“设置单例”中。

我正在使用QT5.4和QMLQuick2。

致以敬意,

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-01-31 13:07:58

别绑住它。因为复选框并不完全依赖于Setting.someSetting

当用户单击复选框时,CheckBox.checked将自行更改。同时,属性绑定不再有效。Settings.someSetting不能在用户单击CheckBox后修改它。因此,checked: Settings.someSetting绑定是错误的。

如果要在组件准备就绪时将初始值赋值给复选框,请使用Component.onCompleted分配它:

代码语言:javascript
复制
CheckBox {
    id: someSettingCheckBox 

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

如果您正在处理更复杂的场景,则在运行时可能会更改Setting.someSetting,并且需要同时更改复选框的状态。捕获onSomeSettingChanged信号并显式更改复选框。只有当程序/widget/ Settings /xxx完成时,才向Settings提交值。

代码语言:javascript
复制
CheckBox { id: someSettingCheckBox }

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

Stack Overflow用户

发布于 2020-10-17 17:14:11

我更喜欢这个解决方案

代码语言:javascript
复制
// 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
}

诀窍是在模型中使用if签入来保护emit。这意味着仍然有一个绑定循环,但只有一个,而不是无限循环。如果check返回false,它就会停止,从而不会发出继续循环的信号。这个解决方案非常干净,您没有收到警告,但是仍然得到绑定的所有好处。

我想谈谈其他解决方案的局限性。

代码语言:javascript
复制
CheckBox {    
    Component.onCompleted: checked = Settings.someSetting
    onCheckedChanged: Settings.someSetting = checked; 
}

在此解决方案中,您将失去绑定。它只能在创建时具有默认设置,并由用户进行更改。如果您展开您的程序,使其他事情改变您的模型中的值,这个特定的视图将无法反映这些更改。

代码语言:javascript
复制
Settings {
    id: mySettings
    onSomeSettingChanged: checkBox.checked = someSetting
}
CheckBox {
    id: checkBox
    onCheckedChanged: mySettings.someSetting = checked
}

这个解决方案是为了解决这些问题而提出来的,但从来没有写出来。它在功能上是完整的。模型更改被反映出来,用户可以更改数据,并且没有绑定循环,因为没有绑定;只有两个离散的赋值。(x: y是绑定,x = y是赋值)

这有几个问题。首先,我认为这是丑陋和不雅,但这可以说是主观的。这里看起来很好,但是如果你有一个模型来代表这个视图中的10个东西,这就变成了信号意大利面。更大的问题是,它不能很好地与代表工作,因为他们只有在需要的情况下存在。

示例:

代码语言:javascript
复制
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
    }
}

你真的能做到。我已经完成了定制的QML信号和连接,但是代码的复杂性让我想要抛出,更糟糕的是,在没有必要的情况下,您可能会强制创建委托。

票数 8
EN

Stack Overflow用户

发布于 2015-01-31 10:48:35

如果您不想创建绑定循环--不要进行绑定,例如,使用代理变量。其他简单的解决方案可以是检查值:

代码语言:javascript
复制
CheckBox {
    checked: Settings.someSetting                         
    onCheckedChanged: {
        if (checked !== Settings.someSetting) {
            Settings.someSetting = checked;
        }
    }
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28250710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档