本页内容

属性绑定

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

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

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

概述

要创建属性绑定,需为属性分配一个 JavaScript 表达式,该表达式计算出的结果即为所需值。最简单的情况下,绑定可以是对另一个属性的引用。以下示例中,蓝色Rectangle 的高度被绑定到其父元素的高度:

Rectangle {
    width: 200; height: 200

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

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

由于 QML 使用符合标准的 JavaScript 引擎,因此绑定可以包含任何有效的 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 函数内部引用的任何属性都将被重新评估。例如,在下面的代码片段中,每当Rectangle 的enabled 属性发生变化时,x 和y 属性的绑定都会被重新评估:

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 作为静态值。此后, height 将保持在这个值上,即使width 发生变化也是如此。静态值的赋值会移除该绑定。

import QtQuick 2.0

Rectangle {
    width: 100
    height: width * 2

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

如果目的是让矩形具有固定高度并停止自动更新,那么这没有问题。但是,如果目的是在width 和height 之间建立新的关系,则必须将新的绑定表达式包裹在 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` 的宽度。若要将 `Rectangle` 的 `height ` 绑定到其自身的 `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 环境限制》。

另请参阅 “使用锚点进行定位”。

© 2026 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.