QML Object Attributes QML对象属性

QML Object Attributes

Every QML object type has a defined set of attributes. Each instance of an object type is created with the set of attributes that have been defined for that object type. There are several different kinds of attributes which can be specified, which are described below.

每一个QML对象类型都定义了一系列属性。每创建一个对象类型的实例,对象内定义的一系列属性就会被创建。接下来我们讨论有哪几种不同种类的属性可被指定。

Attributes in Object Declarations

对象声明内的属性

An object declaration in a QML document defines a new type. It also declares an object hierarchy that will be instantiated should an instance of that newly defined type be created.

QML文档内的对象声明定义一个新的类型。也声明了以新定义的类型为实例的将被实例化的对象层次结构的创建。

The set of QML object-type attribute types is as follows:

这组QML对象系统的属性类型如下:

the id attribute

property attributes

signal attributes

signal handler attributes

method attributes

attached properties and attached signal handler attributes

id属性

属性特征

信号属性

信号处理属性

方法属性

附加属性和附加信号处理属性

These attributes are discussed in detail below.

下面详细讨论这些属性:

The id Attribute

id 属性

Every QML object type has exactly one id attribute. This attribute is provided by the language itself, and cannot be redefined or overridden by any QML object type.

每一个QML对象类型都有一个唯一确定的ID属性。这个属性是由语言自身提供的,并且不能被QML对象类型重定义或者重写。

A value may be assigned to the id attribute of an object instance to allow that object to be identified and referred to by other objects. This id must begin with a lower-case letter or an underscore, and cannot contain characters other than letters, numbers and underscores.

可以分配值给对象实例的id属性让对象被其它对象识别和引用。id必须以小写字母或者下划线开头,并且不能包含除了字母数字和下划线以外的字符。

Below is a TextInput object and a Text object. The TextInput object's id value is set to "myTextInput". The Text object sets its text property to have the same value as the text property of the TextInput, by referring to myTextInput.text. Now, both items will display the same text:

下面是一个 TextInput 对象和一个 Text 对象。 TextInput 对象的 id 值被设置为 "myTextInput" 。 Text 对象设置自己的文本属性和 TextInput 文本属性有相同的值,通过引用 myTextInput.text 。现在,2个项将显示相同的文本:

import QtQuick 2.0

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

An object can be referred to by its id from anywhere within the component scope in which it is declared. Therefore, an id value must always be unique within its component scope. See Scope and Naming Resolution for more information.

在对象被声明的组件范围内的任何地方,通过对象id引用对象。因此,id 值必须是组件范围内唯一的。更多的细节请查看范围<Scope>和命名方案<Naming Resolution>。

Once an object instance is created, the value of its id attribute cannot be changed. While it may look like an ordinary property, the id attribute is not an ordinary property attribute, and special semantics apply to it; for example, it is not possible to access myTextInput.id in the above example.

一旦对象实例被创建,它的id属性值不能被改变。虽然它看起来像一个普通的属性,但是其实它不是一个普通的属性,并且特殊的语义应用与它;例如,在上面的例子中是不可能访问 myTextInput.id 的。

Property Attributes

属性特征

A property is an attribute of an object that can be assigned a static value or bound to a dynamic expression. A property's value can be read by other objects. Generally it can also be modified by another object, unless a particular QML type has explicitly disallowed this for a specific property.

属性是对象的特征,可以分配静态值或绑定动态表达式到属性。属性的值可以被其它对象读取。

通常它也能被另一个对象修改,除非某 QML 类型显式的禁止修改某指定属性。

Defining Property Attributes

定义属性特征

A property may be defined for a type in C++ by registering a Q_PROPERTY of a class which is then registered with the QML type system. Alternatively, a custom property of an object type may be defined in an object declaration in a QML document with the following syntax:

可以通过在C++中注册一个 Q_PROPERTY 到即将被注册进QML类型系统的类来定义属性。另外,一个对象类型的自定义属性可以在对象声明时被定义,在QML文档中使用如下的语法:

    [default] property <propertyType> <propertyName>

In this way an object declaration may expose a particular value to outside objects or maintain some internal state more easily.

通过这种方法一个对象声明可以暴露一个特殊的值到对象之外或者更容易保持一些内部状态。

Property names must begin with a lower case letter and can only contain letters, numbers and underscores. JavaScript reserved words are not valid property names. The default keyword is optional, and modifies the semantics of the property being declared. See the upcoming section on default properties for more information about the default property modifier.

属性名必须以小写字母或者下划线开头,并且不能包含除了字母数字和下划线以外的字符。JavaScript 保留字是无效的属性名。默认关键字是可选的,将修改属性声明时的语义。查看下面的默认属性的章节了解关于默认属性修改的更多信息。

Declaring a custom property implicitly creates a value-change signal for that property, as well as an associated signal handler called on<PropertyName>Changed, where <PropertyName> is the name of the property, with the first letter capitalized.

声明一个自定义属性默认的为此属性创建了一个值改变信号,相关的信号是 on<PropertyName>Changed ,<PropertyName>是第一个字母大写的属性名。

For example, the following object declaration defines a new type which derives from the Rectangle base type. It has two new properties, with a signal handler implemented for one of those new properties:

例如,如下的对象声明基于 Rectangle 定义了一个新类型,它有2个新属性,对这两个属性中的一个实现了信号处理:

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}

Valid Types in Custom Property Definitions

有效的自定义属性类型

Any of the QML Basic Types aside from the enumeration type can be used as custom property types. For example, these are all valid property declarations:

除枚举类型外,任何的QML基本类型可以用来自定义属性类型。例如,这些都是有效的属性声明:

Item {
    property int someNumber
    property string someString
    property url someUrl
}

(Enumeration values are simply whole number values and can be referred to with the int type instead.)

(枚举值是整数值并可以被相关的整型代替。)

Some basic types are provided by the QtQuick module and thus cannot be used as property types unless the module is imported. See the QML Basic Types documentation for more details.

QtQuick模块提供的基本类型是不能作为属性类型使用的,除非导入模块。更多的细节请查看QML基本类型<QML Basic Types>。

Note the var basic type is a generic placeholder type that can hold any type of value, including lists and objects:

注意基本类型 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" }

Additionally, any QML object type can be used as a property type. For example:

此外,任何 QML 对象类型可以作为属性类型被使用。例如:

property Item someItem

property Rectangle someRectangle

This applies to custom QML types as well. If a QML type was defined in a file named ColorfulButton.qml (in a directory which was then imported by the client), then a property of type ColorfulButton would also be valid.

这也适用于自定义QML类型。如果在 ColorfulButton.qml 文件中定义了一个QML类型,那么 ColorfulButton 类型的属性也是有效的。

Assigning Values to Property Attributes

属性特征的值分配

The value of a property of an object instance may specified in two separate ways:

对象实例的属性值可以用2种独立的方法指定:

a value assignment on initialization

an imperative value assignment

初始化赋值

命令式赋值

In either case, the value may be either a static value or a binding expression value.

任何情况下,所赋的值或者是静态值或者是绑定表达式值。

Value Assignment on Initialization

初始化赋值

The syntax for assigning a value to a property on initialization is:

属性的初始化赋值的语法是:

    <propertyName> : <value>

An initialization value assignment may be combined with a property definition in an object declaration, if desired. In that case, the syntax of the property definition becomes:

初始化赋值可以结合对象声明时的属性定义,如果需要。这种情况下,属性定义的的语法变为:

    [default] property <propertyType> <propertyName> : <value>

An example of property value initialization follows:

一个属性值初始化的例子如下:

import QtQuick 2.0

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}

Imperative Value Assignment

命令赋值

An imperative value assignment is where a property value (either static value or binding expression) is assigned to a property from imperative JavaScript code. The syntax of an imperative value assignment is just the JavaScript assignment operator, as shown below:

命令赋值是从命令式的 JavaScript 代码给一个属性分配值。命令赋值的语法就是一个 JavaScript 赋值操作,如下:

    [<objectId>.]<propertyName> = value

An example of imperative value assignment follows:

如下是一个命令赋值的例子:

import QtQuick 2.0

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

Static Values and Binding Expression Values

静态值和绑定表达式的值

As previously noted, there are two kinds of values which may be assigned to a property: static values, and binding expression values. The latter are also known as property bindings.

如前所述,有2种类型的值可以分配给属性:静态值和绑定表达式的值。后者也被称为属性绑定。

Kind Semantics

Static Value A constant value which does not depend on other properties.

Binding Expression A JavaScript expression which describes a property's relationship with other properties. The variables in this expression are called the property's dependencies.

The QML engine enforces the relationship between a property and its dependencies. When any of the dependencies change in value, the QML engine automatically re-evaluates the binding expression and assigns the new result to the property.

不依赖于其它属性的常量值。

描述属性与其它属性关系的JavaScript表达式。表达式内的变量被称为属性的依赖。QML引擎执行属性和它的依赖之间的关系。当任何依赖的值改变,QML引擎自动对绑定的表达式重新求值并将新值赋值给属性。

Here is an example that shows both kinds of values being assigned to properties:

这是一个显示分配2种类型的值给属性的例子:

import QtQuick 2.0

Rectangle {
    // both of these are static value assignments on initialization
    width: 400
    height: 200

    Rectangle {
        // both of these are binding expression value assignments on initialization
        width: parent.width / 2
        height: parent.height
    }
}

Note: To assign a binding expression imperatively, the binding expression must be contained in a function that is passed into Qt.binding(), and then the value returned by Qt.binding() must be assigned to the property. In contrast, Qt.binding() must not be used when assigning a binding expression upon initialization. See Property Binding for more information.

注意: 命令式地分配一个绑定表达式,此绑定表达式必须被包含在一个函数内,这个函数(作为参数)被传递到 Qt.binding() ,Qt.binding() 返回的值必须被分配给属性。相比之下,当分配一个绑定表达式在初始化上时,不需要使用 Qt.binding() 。更多的细节请查看属性绑定<Property Binding>。

Type Safety

类型安全

Properties are type safe. A property can only be assigned a value that matches the property type.

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

For example, if a property is a real, and if you try to assign a string to it, you will get an error:

比如,如果属性是实数,如果你尝试分配字符串给它,你将得到一个错误:

property int volume: "four"  // generates an error; the property's object will not be loaded

Likewise if a property is assigned a value of the wrong type during run time, the new value will not be assigned, and an error will be generated.

同样,如果属性在运行过程中被分配错误的值,新值将不被分配,将产生一个错误。

Some property types do not have a natural value representation, and for those property types the QML engine automatically performs string-to-typed-value conversion. So, for example, even though properties of the color type store colors and not strings, you are able to assign the string "red" to a color property, without an error being reported.

有些属性类型没有自然值表现,对这些属性类型QML引擎自动执行字符串到类型值的转变。所以,例如,虽然颜色属性储存颜色而不是字符串,你也可以分配"red"给一个颜色属性,并不会报告错误。

See QML Basic Types for a list of the types of properties that are supported by default. Additionally, any available QML object type may also be used as a property type.

查看QML基本类型<QML Basic Types>列表,了解默认支持的属性。另外,任何有效的QML基本类型也可以被作为属性类型。

Special Property Types

特殊的属性类型

Object List Property Attributes

对象列表属性特征

A list type property can be assigned a list of QML object-type values. The syntax for defining an object list value is a comma-separated list surrounded by square brackets:

列表类型的属性可以被分配一个(QML对象类型的)列表值。定义列表对象值的语法是被方括号包围的逗号分割的列表。

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

For example, the Item type has a states property that is used to hold a list of State type objects. The code below initializes the value of this property to a list of three State objects:

比如,Item类型有一个用来控制State对象列表的states属性。如下的代码初始化一个属性的值为包含3个State对象(的列表):

import QtQuick 2.0

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

If the list contains a single item, the square brackets may be omitted:

如果列表只包含单独项,可以省略中括号:

import QtQuick 2.0

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

A list type property may be specified in an object declaration with the following syntax:

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

[default] property list<<objectType>> propertyName

and, like other property declarations, a property initialization may be combined with the property declaration with the following syntax:

像其它的属性声明,属性初始化可以连同属性声明使用如下的语法:

[default] property list<<objectType>> propertyName: <value>

An example of list property declaration follows:

如下是一个列表属性声明的例子:

import QtQuick 2.0

Rectangle {
    // declaration without initialization
    property list<Rectangle> siblingRects

    // declaration with initialization
    property list<Rectangle> childRects: [
        Rectangle { color: "red" },
        Rectangle { color: "blue"}
    ]
}

If you wish to declare a property to store a list of values which are not necessarily QML object-type values, you should declare a var property instead.

如果你想声明一个属性去储存那些不需要 QML 对象类型的值的一个列表,你应该声明一个 var 属性代替。

Grouped Properties

属性组

In some cases properties contain a logical group of sub-property attributes. These sub-property attributes can be assigned to using either the dot notation or group notation.

某些情况下属性包含子属性特征的逻辑组。这些子属性特征被分配到每一个使用点(.)符号或组({})符号(的对象内)。

For example, the Text type has a font group property. Below, the first Text object initializes its font values using dot notation, while the second uses group notation:

例如, Text 类型有一个 font 组属性。如下,第一个 Text 对象使用点符号初始化它的 font 值,而第二个(对象)使用组符号(初始化它的 font 值)。

Text {
    //dot notation
    font.pixelSize: 12
    font.b: true
}

Text {
    //group notation
    font { pixelSize: 12; b: true }
}

Grouped property types are basic types which have subproperties. Some of these basic types are provided by the QML language, while others may only be used if the Qt Quick module is imported. See the documentation about QML Basic Types for more information.

分组属性类型是基本类型。一些基本类型是QML语言提供的,有一些在Qt Quick模块被导入后才能使用。更多的细节请查看QML基本类型<QML Basic Types>。

Property Aliases

属性别名

Property aliases are properties which hold a reference to another property. Unlike an ordinary property definition, which allocates a new, unique storage space for the property, a property alias connects the newly declared property (called the aliasing property) as a direct reference to an existing property (the aliased property).

属性别名是另一个属性的引用。不同于一般的属性定义(一般的属性定义分配一个新的独特的存储空间),属性别名连接新声明的属性作为已存在属性的直接引用。

A property alias declaration looks like an ordinary property definition, except that it requires the alias keyword instead of a property type, and the right-hand-side of the property declaration must be a valid alias reference:

属性别名的声明看起来像一般的属性定义,除了它用 alias 关键字替代属性类型,属性声明的右侧必须是一个有效的别名引用:

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

Unlike an ordinary property, an alias can only refer to a object, or the property of a object, that is within the scope of the type within which the alias is declared. It cannot contain arbitrary JavaScript expressions and it cannot refer to objects declared outside of the scope of its type. Also note the alias reference is not optional, unlike the optional default value for an ordinary property; the alias reference must be provided when the alias is first declared.

不同于一般的属性定义,别名只能指向别名被声明的大括号内的对象或者对象的属性。它不能包含任何的 JavaScript 表达式并且不能指向所在类型的大括号外声明的对象。还要注意别名引用不是可选的,不像普通属性的值有可选的默认值;别名引用(的对象)必须被提供当别名第一次声明时。

For example, below is a Button type with a buttonText aliased property which is connected to the text object of the Text child:

例如,如下是一个带 buttonText 别名的按钮类型,别名连接到 Text 子对象的 text 对象:

// Button.qml
import QtQuick 2.0

Rectangle {
    property alias buttonText: textItem.text

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

    Text { id: textItem }
}

The following code would create a Button with a defined text string for the child Text object:

下面的代码会创建一个为子 Text 对象定义了文本字符串的 Button:

Button { buttonText: "Click Me" }

Here, modifying buttonText directly modifies the textItem.text value; it does not change some other value that then updates textItem.text. If buttonText was not an alias, changing its value would not actually change the displayed text at all, as property bindings are not bi-directional: the buttonText value would have changed if textItem.text was changed, but not the other way around.

这里,修改 buttonText 将直接修改 textItem.text 的值;不改变其它的值然后更新 textItem.text 。如果 buttonText 不是别名,改变他的值并不会改变显示的文本,因为属性绑定不是双向的:如果 textItem.text 改变 buttonText 将会被改变,但是反过来就不行。

Considerations for Property Aliases

属性别名的注意事项

Aliases are only activated once a component has been fully initialized. An error is generated when an uninitialized alias is referenced. Likewise, aliasing an aliasing property will also result in an error.

一旦组件被完全初始化别名才被激活。未初始化的别名被引用将产生错误。同样,别名到另一个别名属性也将产生错误。

property alias widgetLabel: label

//will generate an error
//widgetLabel.text: "Initial text"

//will generate an error
//property alias widgetLabelText: widgetLabel.text

Component.onCompleted: widgetLabel.text = "Alias completed Initialization"

When importing a QML object type with a property alias in the root object, however, the property appear as a regular Qt property and consequently can be used in alias references.

当导入的的 QML 对象类型的根对象带有属性别名,无论如何,属性呈现正常的的Qt属性并且因此能被别名引用使用。

It is possible for an aliasing property to have the same name as an existing property, effectively overwriting the existing property. For example, the following QML type has a color alias property, named the same as the built-in Rectangle::color property:

别名属性和已存在的属性拥有相同的名字是可能的,事实上覆盖了已存在属性。例如,如下的 QML 类型有一个 color 属性别名,和原有的 Rectangle::color 属性相同:

Rectangle {
    id: coloredrectangle
    property alias color: bluerectangle.color
    color: "red"

    Rectangle {
        id: bluerectangle
        color: "#1234ff"
    }

    Component.onCompleted: {
        console.log (coloredrectangle.color)    //prints "#1234ff"
        setInternalColor()
        console.log (coloredrectangle.color)    //prints "#111111"
        coloredrectangle.color = "#884646"
        console.log (coloredrectangle.color)    //prints #884646
    }

    //internal function that has access to internal properties
    function setInternalColor() {
        color = "#111111"
    }
}

Any object that use this type and refer to its color property will be referring to the alias rather than the ordinary Rectangle::color property. Internally, however, the red can correctly set its color property and refer to the actual defined property rather than the alias.

任何对象使用这个类型并且指定它的 color 属性将被引用到别名而不是原有的 Rectangle::color 属性。但是,在内部红色可以正确设置它的颜色属性并且指向实际定义的属性,而不是别名。

Default Properties

默认属性

An object definition can have a single default property. A default property is the property to which a value is assigned if an object is declared within another object's definition without declaring it as a value for a particular property.

对象定义可以包含一个单独的的默认属性。如果一个对象(子)声明在另一个对象(父)的定义体内,默认属性是(子对象内)一个被分配为不需要声明它作为具体的属性的值的属性。

Declaring a property with the optional default keyword marks it as the default property. For example, say there is a file MyLabel.qml with a default property someText:

使用可选的 default 关键字声明属性为默认属性。例如,下面的 MyLabel.qml 文件内有一个默认属性 someText:

// MyLabel.qml
import QtQuick 2.0

Text {
    default property var someText

    text: "Hello, " + someText.text
}

The someText value could be assigned to in a MyLabel object definition, like this:

someText 的值可以被分配在 MyLabel 的对象定义内,如下:

MyLabel {
    Text { text: "world!" }
}

This has exactly the same effect as the following:

如下有同样的确切效果:

MyLabel {
    someText: Text { text: "world!" }
}

However, since the someText property has been marked as the default property, it is not necessary to explicitly assign the Text object to this property.

然而, someText 属性被标记为默认属性,所以不需要显式的分配 Text 对象的属性名称。

You will notice that child objects can be added to any Item-based type without explicitly adding them to the children property. This is because the default property of Item is its data property, and any items added to this list for an Item are automatically added to its list of children.

你也可能注意到了子对象可以添加到任何基于Item的类型,而不需要显式将它们添加到子属性上。这是因为 Item 的默认属性是 data 属性,任何添加到 Item 中的对象都自动添加到它的子对象列表。

Default properties can be useful for reassigning the children of an item. See the TabWidget Example, which uses a default property to automatically reassign children of the TabWidget as children of an inner ListView.

默认属性对于重新分配一个项的子项是有用的。查看 TabWidget 例子,使用默认属性自动重新分配 TabWidget 的子对象作为内部的 ListView 的子对象。

Read-Only Properties

只读属性

An object declaration may define a read-only property using the readonly keyword, with the following syntax:

对象声明时使用readonly关键字可以定义只读属性,语法如下:

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

Read-only properties must be assigned a value on initialization. After a read-only property is initialized, it no longer possible to give it a value, whether from imperative code or otherwise.

只读属性必须在初始化时分配值。只读属性初始化后,不管是命令式代码或者其它方式都不可以再对它赋值。

For example, the code in the Component.onCompleted block below is invalid:

例如,Component.onCompleted 后的代码快是无效的:

Item {
    readonly property int someNumber: 10

    Component.onCompleted: someNumber = 20  // doesn't work, causes an error
}

Note: A read-only property cannot also be a default property.

注意:只读属性不能是默认属性。

Property Modifier Objects

属性修改器对象

Properties can have property value modifier objects associated with them. The syntax for declaring an instance of a property modifier type associated with a particular property is as follows:

属性可以有属性值修改器对象和他们关联。声明关联到具体属性的修改器类型实例的语法如下:

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

It is important to note that the above syntax is in fact an object declaration which will instantiate an object which acts on a pre-existing property.

一个非常重要的注意事项是以上的语法实际上是一个对象的实例化的声明,这个对象将作用在已存在的属性。

Certain property modifier types may only be applicable to specific property types, however this is not enforced by the language. For example, the NumberAnimation type provided by QtQuick will only animate numeric-type (such as int or real) properties. Attempting to use a NumberAnimation with non-numeric property will not result in an error, however the non-numeric property will not be animated. The behavior of a property modifier type when associated with a particular property type is defined by its implementation.

某些属性修改器类型可能只适用于特定的属性类型,然而这不是被语言强制执行的。例如, QtQuick 提供的类型 NumberAnimation 类型仅动画作用于数字类型的属性。尝试使用 NumberAnimation 到非数字类型属性将不会得到错误的结果,然而非数字类型的属性将不会产生动画。与特定属性类型关联的属性修改器类型的行为被它的实现定义。

Signal Attributes

信号属性

A signal is a notification from an object that some event has occurred: for example, a property has changed, an animation has started or stopped, or when an image has been downloaded. The MouseArea type, for example, has a clicked signal that is emitted when the user clicks within the mouse area.

信号是当对象的一些事件发生时的消息:例如,属性改变,动画开始或结束,或者图像被下载。拿 MouseArea 类型来说,当用户点击鼠标区域时会触发一个 clicked 信号。

An object can be notified through a signal handler whenever it a particular signal is emitted. A signal handler is declared with the syntax on<Signal> where <Signal> is the name of the signal, with the first letter capitalized. The signal handler must be declared within the definition of the object that emits the signal, and the handler should contain the block of JavaScript code to be executed when the signal handler is invoked.

无论何时特定的信号被触发,可以通过信号处理程序通知对象。信号处理程序使用 on<Signal> 语法声明, <Signal> 是信号名,第一个字母大写。信号处理程序必须声明在触发该信号的对象的定义内,并且处理程序应该包含 JavaScript 代码块当信号处理程序被调用时执行。

For example, the onClicked signal handler below is declared within the MouseArea object definition, and is invoked when the MouseArea is clicked, causing a console message to be printed:

比如,如下的 onClicked 信号处理程序被声明在 MouseArea 对象定义内,并且当 MouseArea 被点击时调用,打印一个终端消息:

import QtQuick 2.0

Item {
    width: 100; height: 100

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

Defining Signal Attributes

定义信号属性

A signal may be defined for a type in C++ by registering a Q_SIGNAL of a class which is then registered with the QML type system. Alternatively, a custom signal for an object type may be defined in an object declaration in a QML document with the following syntax:

在C++中,对于将被注册到QML类型系统的类,可以通过 Q_SIGNAL 定义信号类型。在QML文档中,可以在对象声明内使用如下的语法自定义信号类型:

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

Attempting to declare two signals or methods with the same name in the same type block is an error. However, a new signal may reuse the name of an existing signal on the type. (This should be done with caution, as the existing signal may be hidden and become inaccessible.)

在同一个类型块内试图定义2个同名的信号或方法是错误的。然而,新信号可以重用类型的已存在信号名。(谨慎使用,因为已存在的方法可能被隐藏并且变得不可访问。)

Here are three examples of signal declarations:

这里是信号声明的3个例子:

import QtQuick 2.0

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

If the signal has no parameters, the "()" brackets are optional. If parameters are used, the parameter types must be declared, as for the string and var arguments for the actionPerformed signal above. The allowed parameter types are the same as those listed under Defining Property Attributes on this page.

如果信号没有参数,"()"是可选的。如果参数被使用,参数类型必须被声明,像上面的 actionPerformed 信号的 string 和 var 参数。允许的参数类型和本页列出的定义属性特性是相同的。

To emit a signal, invoke it as a method. Any relevant signal handlers will be invoked when the signal is emitted, and handlers can use the defined signal argument names to access the respective arguments.

触发信号,像调用方法一样调用信号。信号被触发时任何信号相关的处理将被调用,处理程序可以使用信号已定义的参数访问各自的参数。

Property Change Signals

QML types also provide built-in property change signals that are emitted whenever a property value changes, as previously described in the section on property attributes. See the upcoming section on property change signal handlers for more information about why these signals are useful, and how to use them.

QML类型也提供内建的属性改变信号,在信号值改变时被触发,正如前面章节所描述的属性特征。关于为什么这些信号是有用的并且如何使用他们。查看后续的属性改变信号的处理。

Signal Handler Attributes

信号处理程序属性

Signal handlers are a special sort of method attribute, where the method implementation is invoked by the QML engine whenever the associated signal is emitted. Adding a signal to an object definition in QML will automatically add an associated signal handler to the object definition, which has, by default, an empty implementation. Clients can provide an implementation, to implement program logic.

信号处理程序是特殊的方法属性,无论何时,关联的信号被触发时,该方法的实现被QML引擎调用。添加信号到对象定义将自动添加对应的信号处理程序,默认的是一个空的实现。用户可以提供一个实现去实现程序逻辑。

Consider the following SquareButton type, whose definition is provided in the SquareButton.qml file as shown below, with signals activated and deactivated:

考虑下面的的 SquareButton 类型,如下的 SquareButton.qml 中提供定义体,包含信号 activated 和 activated :

// SquareButton.qml
Rectangle {
    id: root

    signal activated(real xPosition, real yPosition)
    signal deactivated

    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onPressed: root.activated(mouse.x, mouse.y)
        onRelased: root.deactivated()
    }
}

These signals could be received by any SquareButton objects in another QML file in the same directory, where implementations for the signal handlers are provided by the client:

这些信号应该被相同目录下的另一个QML文件中的 SquareButton 对象接收,用户提供如下的信号处理程序实现:

// myapplication.qml
SquareButton {
    onActivated: console.log("Activated at " + xPosition + "," + yPosition)
    onDeactivated: console.log("Deactivated!")
}

See the Signal and Handler Event System for more details on use of signals.

更多的细节请查看查看信号和事件处理系统<Signal and Handler Event System>。

Property Change Signal Handlers

属性改变信号的处理

Signal handlers for property change signal take the syntax form on<Property>Changed where <Property> is the name of the property, with the first letter capitalized. For example, although the TextInput type documentation does not document a textChanged signal, this signal is implicitly available through the fact that TextInput has a text property and so it is possible to write an onTextChanged signal handler to be called whenever this property changes:

属性改变的信号的处理程序使用语法 on<Property>Changed ,<Property> 是属性的名字并且第一个字母大写。比如,虽然 TextInput 类型文档没有提供 textChanged 信号,但是通过 TextInput 有一个 text 属性的事实让这个信号是隐士可用的,并且写一个 onTextChanged 信号处理程序(是可能的),无论何时信号改变时被调用。

import QtQuick 2.0

TextInput {
    text: "Change this!"

    onTextChanged: console.log("Text has changed to:", text)
}

Method Attributes

方法属性

A method of an object type is a function which may be called to perform some processing or trigger further events. A method can be connected to a signal so that it is automatically invoked whenever the signal is emitted. See Signal and Handler Event System for more details.

对象类型的方法是一个可以被调用去执行一些处理或触发后续事件的函数。方法可以连接到信号以便信号被触发时它可以被自动调用。更多的细节请查看查看信号和事件处理系统<Signal and Handler Event System>。

Defining Method Attributes

定义方法属性

A method may be defined for a type in C++ by tagging a function of a class which is then registered with the QML type system with Q_INVOKABLE or by registering it as a Q_SLOT of the class. Alternatively, a custom method can be added to an object declaration in a QML document with the following syntax:

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

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

Methods can be added to a QML type in order to define standalone, reusable blocks of JavaScript code. These methods can be invoked either internally or by external objects.

方法被添加到QML类型以便定义独立的可复用的 JavaScript 代码快。方法可以被内部调用,也可以被外部对象调用。

Unlike signals, method parameter types do not have to be declared as they default to the var type.

不同于信号,方法的参数不是必须被定义的,参数默认是 var 类型。

Attempting to declare two methods or signals with the same name in the same type block is an error. However, a new method may reuse the name of an existing method on the type. (This should be done with caution, as the existing method may be hidden and become inaccessible.)

在同一个类型块内试图定义2个同名的方法或信号是错误的。然而,新方法可以重用类型的已存在方法名。(谨慎使用,因为已存在的方法可能被隐藏并且变得不可访问。)

Below is a Rectangle with a calculateHeight() method that is called when assigning the height value:

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

import QtQuick 2.0
Rectangle {
    id: rect

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

    width: 100
    height: calculateHeight()
}

If the method has parameters, they are accessible by name within the method. Below, when the MouseArea is clicked it invokes the moveTo() method which can then refer to the received newX and newY parameters to reposition the text:

如果方法有参数,在方法内可以通过名字访问参数。如下,当 MouseArea 被点击将调用 moveTo() 方法,方法可以引用收到的 newX 和 newY 参数去重置文本位置:

import QtQuick 2.0

Item {
    width: 200; height: 200

    MouseArea {
        anchors.fill: parent
        onClicked: label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label

        function moveTo(newX, newY) {
            label.x = newX;
            label.y = newY;
        }

        text: "Move me!"
    }
}

Attached Properties and Attached Signal Handlers

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

Attached properties and attached signal handlers are mechanisms that enable objects to be annotated with extra properties or signal handlers that are otherwise unavailable to the object. In particular, they allow objects to access properties or signals that are specifically relevant to the individual object.

附加属性和附加信号处理程序是一种使对象被解释为扩展属性或信号处理程序(否则无效)的机制,特别地,这允许对象访问与个别对象明确相关的属性或者信号。

A QML type implementation may choose to create an attaching type with particular properties and signals. Instances of this type can then be created and attached to specific objects at run time, allowing those objects to access the properties and signals of the attaching type. These are accessed by prefixing the properties and respective signal handlers with the name of the attaching type.

QML的类型实现可以选择创建带有特定属性和信号的附加类型。在运行时(附加)类型实例可以被创建并且附加到指定的对象,允许那些对象访问附加类型的属性和信号。这些被以附加类型名为前缀的属性和对应的信号处理程序访问。

References to attached properties and handlers take the following syntax form:

附加属性和处理程序使用如下的语法:

<AttachingType>.<propertyName>

<AttachingType>.on<SignalName>

For example, the ListView type has an attached property ListView.isCurrentItem that is available to each delegate object in a ListView. This can be used by each individual delegate object to determine whether it is the currently selected item in the view:

比如, 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"
    }
}

In this case, the name of the attaching type is ListView and the property in question is isCurrentItem, hence the attached property is referred to as ListView.isCurrentItem.

在这种情况下,附加类型的名字是 ListView 并且界定的属性是 isCurrentItem ,因此被附加的属性是 ListView.isCurrentItem 的引用。

An attached signal handler is referred to in the same way. For example, the Component.onCompleted attached signal handler is commonly used to execute some JavaScript code when a component's creation process has been completed. In the example below, once the ListModel has been fully created, its Component.onCompleted signal handler will automatically be invoked to populate the model:

附加信号处理程序使用相同的引用方法。例如, Component.onCompleted 附加信号处理程序通常用来在组件的创建流程完成时执行 JavaScript 代码。下面的例子,一旦 ListModel 被完全创建,它的 Component.onCompleted 信号处理程序将自动被调用去生成模型:

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 }
}

Since the name of the attaching type is Component and that type has a completed signal, the attached signal handler is referred to as Component.onCompleted.

因为附加类型的名称是 Component 并且有 completed 信号,所以附加信号处理程序是 Component.onCompleted 的引用。

A Note About Accessing Attached Properties and Signal Handlers

访问附加属性和信号处理程序的注意事项

A common error is to assume that attached properties and signal handlers are directly accessible from the children of the object to which these attributes have been attached. This is not the case. The instance of the attaching type is only attached to specific objects, not to the object and all of its children.

一个常见的错误是认为附加属性和信号处理对于那些已附加这些属性的对象的子对象是直接可访问的。事实并非如此。附加类型的实例仅仅附属于特定对象,不属于对象和它的所有子对象。

For example, below is a modified version of the earlier example involving attached properties. This time, the delegate is an Item and the colored Rectangle is a child of that item:

例如,如下是之前的调用附加属性的例子的一个修改版本。这次,代理是 Item 并且 colored Rectangle 是该 Item 的子对象:

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Item {
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: ListView.isCurrentItem ? "red" : "yellow"    // WRONG! This won't work.
        }
    }
}

This does not work as expected because ListView.isCurrentItem is attached only to the root delegate object, and not its children. Since the Rectangle is a child of the delegate, rather than being the delegate itself, it cannot access the isCurrentItem attached property as ListView.isCurrentItem. So instead, the rectangle should access isCurrentItem through the root delegate:

如预期的那样不工作,因为 ListView.isCurrentItem 仅仅是根代理对象的附加,并不是它的子对象的附加。 Rectangle 是代理的子对象,不是代理本身,它不能以 ListView.isCurrentItem 的形式访问 isCurrentItem 附加属性。所以, Rectangle 应该通过根代理访问 isCurrentItem 。

ListView {
    //....
    delegate: Item {
        id: delegateItem
        width: 100; height: 30

        Rectangle {
            width: 100; height: 30
            color: delegateItem.ListView.isCurrentItem ? "red" : "yellow"   // correct
        }
    }
}

Now delegateItem.ListView.isCurrentItem correctly refers to the isCurrentItem attached property of the delegate.

现在 delegateItem.ListView.isCurrentItem 正确的引用了代理的 isCurrentItem 附加属性。

posted on 2016-06-28 18:08  ddev  阅读(3575)  评论(1编辑  收藏  举报