QML 中属性绑定求值的顺序和方式
Posted
技术标签:
【中文标题】QML 中属性绑定求值的顺序和方式【英文标题】:Order and manner of property binding evaluations in QML 【发布时间】:2014-11-20 22:51:40 【问题描述】:据我了解,当在绑定表达式中使用属性时,它们的NOTIFY
信号会连接起来,以在每次更改属性值时发出重新评估表达式的信号。
所以考虑这个简单的例子:
Rectangle
width: 200
height: width - 100
Text
text: "value is " + (parent.width + parent.height)
其中height
属性绑定到width
属性,text
属性绑定到两者。
在这个例子中,不清楚操作的顺序是什么。我的意思是如果width
发生变化,它会发出重新评估引用它的两个表达式。但是width
也会改变height
,这本身也会触发text
的评估。
text
属性是否因此被评估了两次?当width
改变一次,当width
改变height
再一次?或者 QML 可能有一些优化该行为的机制,例如通知信号不会触发实际的重新评估,而只会将表达式标记为“脏”,并且在下一次事件循环迭代时重新评估它们,当所有信号都已传播?即便如此,引擎如何知道在更新text
之前更新height
以避免对后者进行双重重新评估?或者可能连接是直接的而不是排队的,并且使用了一些更复杂的机制来确定重新评估的顺序?或者,如果它恰好是任意顺序,那么 text
可能实际上会重新评估两次?
我真的需要了解它是如何工作的,因为我有一个项目,我在 C++ 端以命令方式修改多个 QML 对象的多个属性,这些属性绑定在 QML 端,我得到非常不一致和不稳定的行为,所以我绝对需要考虑这些工作方式。
【问题讨论】:
【参考方案1】:是的。看起来你是对的,text
将被更新两次。简单的例子:
Rectangle
id: testRect
width: 200
height: width - 100
Text
text: "value is " + (parent.width + parent.height)
onTextChanged:
console.log("text was changed (" + parent.width + "," + parent.height + ")");
MouseArea
anchors.fill: parent
onClicked:
testRect.width = 300
输出:
qml: text was changed (200,100)
qml: text was changed (300,100)
qml: text was changed (300,200)
我猜这是简单的行为,并在更改此项目所基于的某些属性时更新相关属性。
Qt docs advices 避免这种情况 - However, if a binding is overly complex - such as involving multiple lines, or imperative loops - it could indicate that the binding is being used for more than describing property relationships. Complex bindings can reduce code performance, readability, and maintainability. It may be a good idea to redesign components that have complex bindings, or at least factor the binding out into a separate function.
【讨论】:
我在评论部分找到kdab.com/qml-engine-internals-part-2-bindings“仅供参考:首次加载组件时,QML 引擎将尝试以最小化绑定重新评估的顺序评估绑定”,但我想它不会具有很大的价值,因为即使在上述示例这样简单的情况下它也会失败。这对于 Qt 来说似乎非常不专业......以上是关于QML 中属性绑定求值的顺序和方式的主要内容,如果未能解决你的问题,请参考以下文章