据我了解,当属性在绑定表达式中使用时,它们的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 端,并且我得到了非常不一致和不稳定的行为,所以我绝对需要考虑这些工作方式。
是的。 看起来你是对的,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文档建议避免这种情况 - 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.