属性绑定

一个对象的属性可以分配一个静态值,在明确分配新值之前保持不变。然而,为了充分利用 QML 及其对动态对象行为的内置支持,大多数 QML 对象都使用了属性绑定

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

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

概述

要创建属性绑定,可为一个属性分配一个 JavaScript 表达式,该表达式会求值到所需的值。最简单的绑定可以是对另一个属性的引用。以下面的示例为例,其中蓝色Rectangle 的高度绑定到其父对象的高度:

Rectangle {
    width: 200; height: 200

    Rectangle {
        width: 100
        height: parent.height
        color: "blue"
    }
}

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

绑定可以包含任何有效的 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()

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

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 函数中引用的任何属性,如果本身被用作绑定,都将被重新评估。例如,在下面的代码段中,每当Rectangleenabled 属性发生变化时,就会重新评估xy 属性的绑定:

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

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

从语法上讲,绑定可以是任意复杂的。但是,如果绑定过于复杂,如涉及多行或强制性循环,则可能表明绑定的用途超出了描述属性关系的范围。复杂的绑定会降低代码的性能、可读性和可维护性。不妨重新设计具有复杂绑定的组件,或至少将绑定分解为一个单独的函数。一般来说,用户不应依赖绑定的评估顺序。

从 JavaScript 创建属性绑定

带有绑定的属性会根据需要自动更新。但是,如果随后通过 JavaScript 语句为该属性分配了静态值,则绑定将被移除。

例如,下面的Rectangle 最初确保其height 总是其width 的两倍。但是,当按下空格键时,width*3 的当前值将作为静态值分配给height 。此后,即使width 发生变化,height 也将保持该值不变。静态值的赋值会消除绑定。

import QtQuick 2.0

Rectangle {
    width: 100
    height: width * 2

    focus: true
    Keys.onSpacePressed: {
        height = width * 3
    }
}

如果目的是给矩形一个固定的高度并停止自动更新,那么这不是问题。但是,如果目的是在widthheight 之间建立新的关系,则必须用 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'的宽度,而不是Rectangle'的宽度。要将Rectangleheight 与自己的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 环境限制

另请参阅 使用锚点定位

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.