为什么 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 至少可以警告可能存在的歧义。
这很奇怪,因为我在另一个 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 至少可以警告可能存在的歧义。