一个QML文档中定义了一个对象类型,其中对象声明部分除了指定对象包含的子对象外,主要是对对象属性进行声明。QML对象类型的属性分为如下一些类型:
id属性
property属性
信号属性
信号handler属性
方法属性
附加属性及附加信号handler属性
枚举属性
以下各小节会针对每种类型的属性进行介绍:
1、id属性
id属性包含的是对象实例的标识符,其他对象可以通过这个属性值访问这个对象实例。id属性不能被自定义属性覆盖。id属性的值必须是以小写字母或下划线开头,而且他不能包含除字母、数字及下划线以外的其他字符。
2、property属性
一个property属性可以用静态值对其赋值,也可以将它与一个动态表达式绑定。property属性可以被其他对象读取,也可以被其他对象修改。
(1)property属性声明语法如下:
[default] [required] [readonly] property <propertyType> <propertyName>
<propertyType>指定了属性的数据类型,所有QML数值类型(除枚举类型外),以及QML对象类型都可以作为属性类型
<propertyName>指定了属性的名称
[readonly]指定属性是只读的,只读属性需要在对象初始化时指定其值。在后续运行时,它的值不能被修改。
[required]指定属性在对象初始化时必须被赋值,如果没有赋值,则对象实例化会失败
[default]指定当前属性为默认属性。 一个对象中可以指定一个property属性为默认属性。在一个对象声明中,如果没有显示将一个子对象赋值给某个属性,则这个子对象会被赋值给默认属性。
(2)可以通过以下两种方式为property属性
在对象初始化时为属性赋值,它的通用语法如下:
<propertyName> : <value>
也可以在属性定义的时候为属性赋值:
[default] property <propertyType> <propertyName> : <value>
一个对象初始化时赋值的例子如下:
import QtQuick 2.0
Rectangle {
color: "red"
property color nextColor: "blue" // combined property declaration and initialization
}
还可以在javaScript代码中对属性进行赋值:
[<objectId>.]<propertyName> = value
一个在javaScript代码中为属性赋值的例子如下:
import QtQuick 2.0
Rectangle {
id: rect
Component.onCompleted: {
rect.color = "red"
}
}
(3)属性绑定
可以将一个javaScript表达式赋值给一个属性,此时表达式中出现的属性都会与被赋值属性进行绑定。当表达式中的某个属性的值发生变化时,QML引擎会自动更新被赋值属性的值。
(4)property属性是类型安全的
如果为一个属性赋一个错误类型的值,属性值不会被修改,同时会报出一个错误。对于某些属性类型的值没有自然数值表示,此时QML引擎会进行字符串到目标类型的转换,例如:可以将“red”赋值给一个color类型的属性。
(5)list类型属性
可以通过如下语法为list类型属性赋值:
[ <item 1>, <item 2>, ... ]
一个为list类型属性赋值的例子如下:
Item {
states: [
State { name: "loading" },
State { name: "running" },
State { name: "stopped" }
]
}
如果所赋的值中仅包含一个对象,则可以省略中括号
也可以在list属性定义时为其赋值:
[default] property list<<objectType>> propertyName: <value>
(6)分组属性
如果一个属性包含子属性逻辑分组,那么可以采用特殊语法为其赋值,例如:
Text {
//dot notation
font.pixelSize: 12
font.b: true
}
其中font就是一个分组属性。
(7)属性别名
属性别名保存的是对另外一个属性的引用。
属性别名只能引用他所在的对象类型内部的属性。
属性别名不能引用附加属性
属性别名不能引用层级大于等于3层的属性
属性别名的定义语法如下:
[default] property alias <name>: <alias reference>
其中reference必须指定。
类型别名只能在对象被完全初始化后才能被使用。
3、信号属性
一个对象类型可以定义自己的信号属性。它的语法如下:
signal <signalName>[([<parameterName>: <parameterType>[, ...]])]
<signalName>是信号的名称
[([<parameterName>: <parameterType>[, ...]])]是信号的参数列表,如果信号没有参数则可以省略参数列表
以下是一个信号属性定义的实例:
signal actionPerformed(action: string, actionResult: int)
参数列表中也可以省略冒号。但是更推荐的是保留冒号。
发送一个信号只需要像调用方法一样调用这个信号就可以了。
4、信号handler属性
信号属性是一类特殊的方法属性,它由QML引擎自动调用。当定义一个信号时,QML会自动为对象类型定义一个信号handler,这个handler实现是空的。这个自动定义的handler的名字以“on”开头以信号名称结尾。(信号及handler会以单独的一篇文章进行详细介绍)。
每一个property属性都有一个信号,当属性值被修改时,QML引擎会自动发送这个信号。对应的,每一个属性也具有onPropertyNameChanged信号handler用户接收属性修改信号。
5、方法属性
可以在对象类型的中定义方法属性,方法属性实际上是一个javaScript函数。与信号属性不同,方法属性参数列表不需要必须指定数据类型。方法属性的定义语法如下:
function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }
6、附加属性
附加属性允许通过附加类型(attaching类型)对属性进行访问,它的语法如下:
<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>
一个访问附加属性的实例如下:
ListView {
width: 240; height: 320
model: 3
delegate: Rectangle {
width: 100; height: 30
color: ListView.isCurrentItem ? "red" : "yellow"
}
}
在这个例子中listView.isCurrentItem就是一个附加属性。
附加属性实际上是定义在一个中间附加类型(attached类型)中的。当对象访问附加属性时,QML引擎会调用附加类型(attaching类型)的qmlAttachedProperties()函数创建中间附加类型(attached类型),并将其附加给当前对象(attachee类型)。以上例子中ListView就是附加类型(attaching类型),delegate就是当前类型(attachee类型)。
7、枚举属性
枚举属性定义了一个固定的集合,集合中包含了命名项。
枚举类型定义及使用的实例如下:
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
}