为什么 Qt QML 没有正确绑定属性?

Why Qt QML doesn't properly bind properties?

这很奇怪,因为我在另一个 QML 文件中使用了几乎相同的模式并且它工作正常!我确定我不会在任何地方重新分配值(我所知道的唯一可以使 属性 静态的东西)! 我有这样的东西(这是一个简化的例子,可能按预期工作):

Item {
    property bool isExpanded: false
    MouseArea {
        anchors.fill: parent
        onClicked: {
            isExpanded = !isExpanded
            console.log(isExpanded)
            console.log(myId.visible)
        }
    }
    MyCustomItem {
        id: myId
        visible: isExpanded
        // other stuff
    }
}
单击后

IsExpanded 发生变化,但 Item 可见性始终保持不变!我的项目还有许多其他属性(例如 height: isExpanded ? someval : 0),这些属性也不会改变!如果我总是手动更改所有内容,它会起作用,但那有什么意义呢?在另一个 QML 中,我使用了类似的模式并且它有效!

但是! 如果我输入,例如 onDoubleClicked/按下另一个按钮: myId.visible = Qt.binding(function() {return isExpanded}) 它可以正常工作!因此,由于某些未知原因,它没有 'bind' 它们应该在常规 属性 声明 (visible: isExpanded) 中。

所以问题是,我真的需要明确地告诉 Qt 绑定 属性 以使其工作吗?

编辑: 澄清一下:我确定我不会在任何地方重新分配可见 属性。我仔细检查了一下。尽管 qml 大小只有大约 100 行,但我使用 ctrl+f 查找任何提到可见的内容并找到 none 除了已经提到的。 如果有更可靠的方法来判断什么来自/检查某处或某处可能的重新分配,请告诉。

So the question is, do I really need to explicitly tell Qt to bind property to make it work?

是的。

声明 属性 时,您可以使用绑定语法,例如visible: isExpanded。但是使用普通 JavaScript 语法(即赋值运算符)在命令式代码中设置 属性 将破坏任何现有绑定并覆盖 属性 的值。如果要在命令式代码中显式设置 属性 绑定,请使用 Qt.binding() 方法 (docs).

尽管您的实际问题是由于成为 QML 范围规则的受害者。您的 MyCustomItem 类型有一个 isExpanded 属性,因此当您声明时:

MyCustomItem {
    id: myId
    visible: isExpanded
    // other stuff
}

您实际上是将 visible 绑定到 MyCustomItem::isExpanded。因此,要明确指出您指的是哪个 isExpanded

Item {
    id: base
    property bool isExpanded: false
    MouseArea {
        anchors.fill: parent
        onClicked: {
            isExpanded = !isExpanded
            console.log(isExpanded)
            console.log(myId.visible)
        }
    }
    MyCustomItem {
        id: myId
        visible: base.isExpanded
        // other stuff
    }
}

我找到问题了!非常不明显(没有在任何地方找到记录)并且它默默地失败了。 问题是 MyCustomItem 包含一个 属性 与外部布尔 属性 isExpanded 同名,所以在这段代码中:

MyCustomItem {
    id: myId
   visible: isExpanded
 // other stuff
}

isExpanded 来自 MyCustomItem。但没有任何迹象表明。好吧,现在我知道这可能会发生,并且如果它再次发生可能会发现它,但这确实是违反直觉的。如果不是我的东西而是别人的,而我不知道它有这样的 属性 怎么办? Qt creator 至少可以警告可能存在的歧义。