QML参考指南03:QML属性绑定

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

属性绑定是QML的核心功能,它使开发人员可以指定不同对象属性之间的关系。当属性的依赖项的值更改时,该属性将根据指定的关系自动更新。

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

总览

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

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

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

绑定可以包含任何有效的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语句为属性分配了静态值,则绑定将被删除。

例如,下面的矩形最初确保其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的宽度。到绑定矩形的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环境限制。

发布了52 篇原创文章 · 获赞 4 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/caridle/article/details/105693938
QML