属性绑定
对象的属性可以分配一个静态值,这个值在未被明确分配新的值之前保持不变。然而,为了最大限度地利用 QML 及其内置对动态对象行为的支持,大多数 QML 对象都使用 属性绑定。
属性绑定是 QML 的核心功能,允许开发者指定不同对象属性之间的关系。当一个属性的 依赖 值改变时,该属性将根据指定的关系自动更新。
在幕后,QML 引擎监视属性的依赖(即在绑定表达式中的变量)。当检测到变化时,QML 引擎会重新评估绑定表达式并将其结果应用到属性上。
概览
要创建属性绑定,需要将一个属性分配一个计算结果为所需值的 JavaScript 表达式。在最简单的形式中,绑定可能是指向另一个属性的引用。以下是一个示例,其中蓝色的 Rectangle 的高度绑定到其父元素的高度
每当父矩形的高度发生变化时,蓝色矩形的高度将自动更新到相同的值。
绑定可以包含任何有效的 JavaScript 表达式或语句,因为 QML 使用了一个符合标准的 JavaScript 引擎。绑定可以访问对象属性、调用方法和使用内置的 JavaScript 对象,如 Date
和 Math
。以下是前一个示例的一些其他可能的绑定
height: parent.height / 2 height: Math.min(parent.width, parent.height) height: parent.height > 100 ? parent.height : parent.height/2 height: { if (parent.height > 100) return parent.height else return parent.height / 2 } height: someMethodThatReturnsHeight()
以下是一个涉及更多对象和类型的更复杂示例
Column { id: column width: 200 height: 200 Rectangle { id: topRect width: Math.max(bottomRect.width, parent.width/2) height: (parent.height / 3) + 10 color: "yellow" TextInput { id: myTextInput text: "Hello QML!" } } Rectangle { id: bottomRect width: 100 height: 50 color: myTextInput.text.length <= 10 ? "red" : "blue" } }
在上一个示例中,
topRect.width
依赖于bottomRect.width
和column.width
topRect.height
依赖于column.height
bottomRect.color
依赖于myTextInput.text.length
在语法上,绑定可以是任意复杂的。但是,如果绑定过于复杂——如涉及多行或命令式循环——这可能表明绑定被用于描述属性关系之外的更多目的。复杂的绑定可能会降低代码的性能、可读性和可维护性。重新设计具有复杂绑定的组件,或者至少将绑定分解到独立的函数中,可能是一个好主意。作为一个一般规则,用户不应依赖于绑定评估的顺序。
从 JavaScript 创建属性绑定
具有绑定的属性将根据需要自动更新。但是,如果该属性稍后被 JavaScript 语句分配了静态值,则绑定将被移除。
例如,下面的矩形最初确保其高度
始终是其宽度
的两倍。然而,当按下空格键时,width*3
的当前值将被作为静态值分配给高度
。之后,高度将保持在这个值上固定,即使宽度发生变化。分配静态值会移除绑定。
import QtQuick 2.0 Rectangle { width: 100 height: width * 2 focus: true Keys.onSpacePressed: { height = width * 3 } }
如果意图是给矩形一个固定的高度并停止自动更新,那么这没问题。然而,如果意图是建立宽度
和高度
之间的新关系,那么新的绑定表达式必须包裹在Qt.binding()函数中
import QtQuick 2.0 Rectangle { width: 100 height: width * 2 focus: true Keys.onSpacePressed: { height = Qt.binding(function() { return width * 3 }) } }
现在,按下空格键后,矩形的高度将继续自动更新,始终是宽度的三倍。
调试绑定覆盖
在QML应用中,意外使用JavaScript语句中的静态值覆盖绑定是常见的错误原因。为了帮助开发者追踪这类问题,QML引擎能够在由于命令式赋值而丢失绑定时发出消息。
为了生成这样的消息,您需要启用qt.qml.binding.removal
记录类别的信息输出,例如通过调用
QLoggingCategory::setFilterRules(QStringLiteral("qt.qml.binding.removal.info=true"));
有关启用日志类别的输出的更多信息,请参阅QLoggingCategory文档。
请注意,在某些情况下覆盖绑定是完全合理的。QML引擎生成的任何消息都应被视为诊断工具,而不一定是进一步调查之前的问题的证据。
使用this
与属性绑定
从JavaScript创建属性绑定时,可以使用this
关键字来指代接收绑定的对象。这对于解决属性名歧义是有帮助的。
例如,下面的Component.onCompleted
处理程序是在Item的作用域中定义的。在这个作用域内,width
指的是Item的宽度,而不是矩形的宽度。为了将矩形的高度
绑定到其自身的width
,绑定表达式必须显式地引用this.width
(或者也可以使用rect.width
)
Item { width: 500 height: 500 Rectangle { id: rect width: 100 color: "yellow" } Component.onCompleted: { rect.height = Qt.binding(function() { return this.width * 2 }) console.log("rect.height = " + rect.height) // prints 200, not 1000 } }
注意:在属性绑定之外,this
的值是没有定义的。有关详细信息,请参阅JavaScript Environment Restrictions
另请参阅使用锚定位.
© 2024 Qt公司股份公司。此处包含的文档贡献的版权归其各自所有者。本提供的文档是根据自由软件基金会发布的GNU自由文档许可证版本1.3的条款许可的。Qt和相应的商标是芬兰及其它国家的Qt公司注册的商标。所有其他商标均为各自所有者的财产。