属性绑定

绑定对象属性

对象的属性可以被赋予一个静态值,该值保持不变,直到显式赋予新值。然而,为了充分利用QML及其对动态对象行为的内置支持,大多数QML对象使用属性绑定

属性绑定是QML的一个核心特性,它允许开发者指定不同对象属性之间的关系。当一个属性的依赖项值发生变化时,该属性会根据指定的关系自动更新。

在幕后,QML引擎监视属性的依赖关系(即绑定表达式中的变量)。当检测到变化时,QML引擎重新评估绑定表达式并将新结果应用于属性。

概述

要创建一个属性绑定,需要将一个属性赋值为一个JavaScript表达式,该表达式计算得出所需的值。最简单的绑定可能是对另一个属性的引用。以下面的例子为例,蓝色矩形的高度绑定到其父级的高度:

每当父矩形的高度发生变化时,蓝色矩形的高度会自动更新为相同的值。

绑定可以包含任何有效的JavaScript表达式或语句,因为QML使用符合标准的JavaScript引擎。绑定可以访问对象属性、调用方法并使用内置的JavaScript对象,例如DateMath。以下是前一个示例的其他可能绑定:

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()

下面是一个涉及更多对象和类型的更复杂示例:

在前面的例子中,

  • topRect.width 依赖于 bottomRect.widthcolumn.width

  • topRect.height 依赖于 column.height

  • bottomRect.color 取决于 myTextInput.text.length

此外,任何在JavaScript函数中引用的属性,如果该函数本身被用作绑定,将会被重新评估。例如,在下面的代码片段中,每当Rectangleenabled属性发生变化时,xy属性的绑定将会被重新评估:

Rectangle {
    x: rectPosition()
    y: rectPosition()
    width: 200
    height: 200
    color: "lightblue"

    function rectPosition() {
        return enabled ? 0 : 100
    }
}

从语法上讲,绑定允许具有任意复杂性。然而,如果绑定过于复杂——例如涉及多行或命令式循环——这可能表明绑定被用于不仅仅是描述属性关系。复杂的绑定可能会降低代码的性能、可读性和可维护性。重新设计具有复杂绑定的组件,或者至少将绑定提取到一个单独的函数中,可能是一个好主意。作为一般规则,用户不应依赖绑定的评估顺序。

从JavaScript创建属性绑定

具有绑定的属性会根据需要自动更新。然而,如果该属性后来通过JavaScript语句分配了一个静态值,绑定将被移除。

例如,下面的矩形最初确保其height始终是其width的两倍。然而,当按下空格键时,width*3的当前值将被分配给height作为一个静态值。之后,即使width发生变化,height也将保持固定在这个值。静态值的分配会移除绑定。

如果目的是给矩形一个固定的高度并停止自动更新,那么这不是问题。然而,如果目的是在widthheight之间建立新的关系,那么新的绑定表达式必须包装在Qt.binding()函数中:

现在,按下空格键后,矩形的高度将继续自动更新,始终保持其宽度的三倍。

调试绑定的覆盖

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的宽度,而不是Rectangle的宽度。要将Rectangle的height绑定到它自己的width,绑定表达式必须明确引用this.width(或者,rect.width):

注意

this 的值在属性绑定之外未定义。详情请参阅 JavaScript Environment Restrictions

另请参阅

使用锚点进行定位