QML对象属性

每个 QML 对象类型都有一组已定义的属性。对象类型的每个实例都是使用为该对象类型定义的属性集创建的。

一、id 属性

每个 QML 对象类型都只有一个 id 属性。 该属性由语言本身提供,不能被任何 QML 对象类型重新定义或覆盖。

id 可用于其他对象识别和引用该对象。

id 必须以小写字母或下划线开头,并且不能包含字母、数字和下划线以外的字符。

一旦创建了对象实例,其 id 属性的值就无法更改。

二、自定义属性

property 是QML自定义属性修饰符。

2.1、定义属性

通过注册一个类的 Q_PROPERTY,然后在 QML 类型系统中注册,可以为 C++ 中的类型定义一个属性。或者,可以使用以下语法在 QML 文档的对象声明中定义对象类型的自定义属性:

[default] [required] [readonly] property <propertyType> <propertyName>

通过这种方式,对象声明可以将特定值暴露给外部对象或更容易地维护一些内部状态。

属性名称必须以小写字母开头,并且只能包含字母、数字和下划线。defaultrequired readonly 关键字是可选的,用于修改所声明属性的语义。

声明自定义属性隐式地为该属性创建一个值更改信号,以及一个名为 on<PropertyName>Changed 的​​关联信号处理程序,其中 <PropertyName> 是属性的名称,首字母大写。

例如,以下对象声明定义了一个派生自 Rectangle 基类型的新类型。它有两个新属性,并为其中一个新属性实现了信号处理程序:

Rectangle 
{
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("下一个颜色将是: " + nextColor.toString())
}

2.2、自定义属性定义中的有效类型

除了枚举类型之外的任何 QML 基本类型都可以用作自定义属性类型(枚举值只是整数值,可以用 int 类型代替。)。

    property int someNumber
    property string someString
    property url someUrl

var 是一个通用的占位符类型,可以保存任何类型的值,包括列表和对象:

property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }

此外,任何 QML 对象类型(包括自定义QML类型)都可以用作属性类型。 

property Item someItem
property Rectangle someRectangle

2.3、类型安全

属性是类型安全的。 只能为属性分配与属性类型匹配的值。

例如,如果一个属性是一个实数,如果试图给它分配一个字符串,就会报错:

property int volume: "four"  // 报错

某些属性类型没有自然值表示,对于这些属性类型,QML 引擎会自动执行字符串到类型值的转换。例如,即使颜色类型的属性存储颜色而不是字符串,也可以将字符串“red”分配给颜色属性。

2.4、特殊属性类型

2.4.1、对象列表属性

定义对象列表值的语法是用方括号括起来的逗号分隔列表:

[ <item 1>, <item 2>, ... ]

例如,Item 类型的 states 属性,用于保存 State 类型对象的列表。

import QtQuick 2.0

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

如果列表包含单个项目,则可以省略方括号:

import QtQuick 2.0

Item {
    states: State { name: "running" }
}

可以使用以下语法在对象声明中指定列表类型属性:

[default] property list<<objectType>> propertyName

import QtQuick 2.0

Rectangle {
    // // 没有初始化的声明
    property list<Rectangle> siblingRects

    // 带初始化的声明
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

2.4.2、分组属性

在某些情况下,属性包含子属性属性的逻辑组。 可以使用点表示法组表示法来分配这些子属性属性。

Text {
    //点表示法
    font.pixelSize: 12
    font.bold : true
}

Text {
    //组表示法
    font { pixelSize: 12; bold : true }
}

2.5、属性别名

属性别名是保存对另一个属性的引用的属性。与为属性分配新的唯一存储空间的普通属性定义不同,属性别名将新声明的属性连接为对现有属性的直接引用。

属性别名声明看起来像一个普通的属性定义,除了它需要 alias 关键字而不是属性类型,并且属性声明的右侧必须是有效的别名引用:

[default] property alias <name>: <alias reference>

与普通属性不同,别名具有以下限制:

  • 它只能引用在声明别名的类型范围内的对象或对象的属性。
  • 它不能包含任意的 JavaScript 表达式
  • 它不能引用在其类型范围之外声明的对象。
  • 它在首次声明别名时必须提供别名引用。
  • 它不能引用附加属性。
  • 它不能引用深度为 3 或更大的层次结构内的属性。此代码将不起作用:
property alias color: myItem.myRect.border.color

Item {
    id: myItem
    property Rectangle myRect
}

例如,下面是一个带有 buttonText 别名属性的 Button 类型,该属性连接到 Text 子项的文本对象:

// Button.qml
import QtQuick 2.0

Rectangle {
    property alias buttonText: textItem.text

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

以下代码将为子 Text 对象创建一个带有已定义文本字符串的 Button:

Button { buttonText: "Click Me" }

修改 buttonText 将直接修改textItem.text的值。这可以用于在定义控件时设置可在外部修改的属性

2.5.1、属性别名的注意事项

  • 引用未初始化的别名时会生成错误。
  • 引用另一个别名属性时会生成错误。
  • 别名属性可能与现有属性同名,从而可以覆盖现有属性。

2.6、默认属性

一个对象定义可以有一个默认属性。使用可选的 default 关键字声明属性将其标记为默认属性。

2.7、必要属性

对象声明可以使用 required 关键字定义对象实例时必须设置的属性

required property <propertyType> <propertyName>

required <propertyName>

如果可以静态检测,缺少必要属性将导致 QML 应用程序无法启动。在动态实例化 QML 组件的情况下(例如通过 Qt.createComponent()),缺少必要属性会导致警告和空返回值。

// ColorRectangle.qml
Rectangle {
    required color
}

不能为 QML 中的必需属性分配初始值,因为这会直接违背必需属性的预期用途。

2.8、只读属性

对象声明可以使用 readonly 关键字定义只读属性。

readonly property <propertyType> <propertyName> : <initialValue>

必须在初始化时为只读属性分配一个值。只读属性初始化后,无论是通过命令式代码还是其他方式,都无法再为其赋值。

只读属性不能同时是默认属性。

2.9、属性修饰符对象

属性可以具有与其关联的属性值修饰符对象。

声明与特定属性关联的属性修饰符类型的实例的语法如下:

<PropertyModifierTypeName> on <propertyName>
{
    // 对象实例的属性
}
    NumberAnimation on x 
    { 
        to: 50; duration: 1000 
    }

这通常称为“on”语法。上述语法实际上是一个对象声明,它将实例化一个对象,该对象作用于预先存在的属性。

三、信号属性

信号是来自对象的某个事件发生的通知。

每当发出特定信号时,都可以通过信号处理程序通知对象。

信号处理程序使用 on<Signal> 语法声明,其中 <Signal> 是信号的名称,首字母大写。信号处理程序必须在发出信号的对象的定义中声明,并且处理程序应包含调用信号处理程序时要执行的 JavaScript 代码块。

import QtQuick 2.0

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

3.1、定义信号属性

可以通过注册一个 C++ 中的类型定义一个信号,然后将其注册到 QML 类型系统。 或者,可以使用以下语法在 QML 文档的对象声明中定义对象类型的自定义信号: 

signal <signalName>[([<type> <parameter name>[, ...]])]

import QtQuick 2.0

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(string action, var actionResult)
}

如果信号没有参数,则“()”括号是可选的。 如果使用参数,则必须声明参数类型。

要发出信号,请将其作为方法调用。

四、方法属性

方法是一个函数。方法可以连接到信号,以便在发出信号时自动调用它。 

4.1、定义方法属性

可以通过标记类的函数在 C++ 中为类型定义方法,然后使用 Q_INVOKABLE 将其注册到 QML 类型系统,或将其注册为类的 Q_SLOT。 或者可以使用以下语法将自定义方法添加到 QML 文档中的对象声明中:

function <functionName>([<parameterName>[, ...]]) { <body> }

可以将方法添加到 QML 类型以定义独立的、可重用的 JavaScript 代码块。 这些方法可以在内部或由外部对象调用。

与信号不同,方法参数类型不必声明,因为它们默认为 var 类型。

下面是一个带有 calculateHeight() 方法的矩形,该方法在分配高度值时被调用:

import QtQuick 2.0
Rectangle {
    id: rect

    function calculateHeight() {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

五、附加属性和附加信号处理程序

附加属性和附加信号处理程序是一种机制,使对象能够使用额外属性或信号处理程序。特别地,它们允许对象访问与单个对象特别相关的属性或信号

QML 类型实现可以选择在 C++ 中创建具有特定属性和信号的附加类型。然后可以在运行时创建此类型的实例并将其附加到特定对象,从而允许这些对象访问附加类型的属性和信号。 这些是通过使用附加类型的名称为属性和相应的信号处理程序添加前缀来访问的。

对附加属性和处理程序的引用采用以下语法形式:

<AttachingType>.<propertyName>

<AttachingType>.on<SignalName>

例如,ListView 类型有一个附加属性 ListView.isCurrentItem,可用于 ListView 中的每个委托对象。每个单独的委托对象都可以使用它来确定它是否是视图中当前选定的项目:

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

附加的信号处理程序以相同的方式引用。例如,Component.onCompleted 附加信号处理程序通常用于在组件的创建过程完成时执行一些 JavaScript 代码。

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: ListModel {
        id: listModel
        Component.onCompleted: {
            for (var i = 0; i < 10; i++)
                listModel.append({"Name": "Item " + i})
        }
    }
    delegate: Text { text: index }
}

六、枚举属性

枚举提供了一组固定的命名选择。 可以使用 enum 关键字在 QML 中声明它们:

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }
}

如上所示,枚举类型(例如 TextType)和值(例如 Normal)必须以大写字母开头。

值通过 <Type>.<EnumerationType>.<Value> <Type>.<Value> 引用。

// MyText.qml
Text {
    enum TextType {
        Normal,
        Heading
    }

    property int textType: MyText.TextType.Normal

    font.bold: textType == MyText.TextType.Heading
    font.pixelSize: textType == MyText.TextType.Heading ? 24 : 12
}
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值