QML components have properties that can be read and modified by other objects. In QML, properties serve many purposes but their main function is to bind to values. Values may be a 基本类型 , or other QML elements.
The syntax for properties is:
[default] property <type> <name>[: defaultValue]
Elements already possess useful properties but, to create custom properties, precede the property name with the keyword
property
.
Rectangle { width: 320; height: 240 color: "lightblue" focus: true property int counter property real area: 100.45 }
QML property rules coincide with many of JavaScript's property rules, for example, property names must begin with a lowercase letter. JavaScript reserved words are not valid property names.
Property binding is a declarative way of specifying the value of a property. Binding allows a property's value to be expressed as an JavaScript expression that defines the value relative to other property values or data accessible in the application. The property value is automatically kept up to date if the other properties or data values change.
Property bindings are created in QML using the colon "
:
" before the value:
Rectangle { width: parent.width }
The property binding causes the width of the
Rectangle
to update whenever the
parent
's width changes.
QML extends a standards compliant JavaScript engine, so any valid JavaScript expression can be used as a property binding. Bindings can access object properties, make function calls and even use built-in JavaScript objects such as
Date
and
数学
.
function calculateArea(width, height) { return (width * height) * 0.5 } Rectangle { width: 150; height: 75 property real area: calculateArea(width, height) property real parentArea: calculateArea(parent.width,parent.height) color: { if (area > parentArea) "blue"; else "red" } }
While syntactically bindings can be of arbitrary complexity, if a binding starts to become overly complex - such as involving multiple lines, or imperative loops - it may be better to refactor the component entirely, or at least factor the binding out into a separate function.
When working with both QML and JavaScript, it is important to differentiate between QML property binding and JavaScript value assignment. In QML, a property binding is created using the colon "
:
".
Rectangle { width: parent.width }
The property binding causes the width of the
Rectangle
to update whenever the
parent
's width changes.
Assigning a property value (using the equals sign "
=
") does not create a property binding.
Rectangle { Component.onCompleted: { width = 150 } }
Instead of creating a property binding, the assignment simply sets the
Rectangle
width
value to a number when the
Component.onCompleted
code is invoked.
Assigning a value to a property that is already bound will remove the previous binding. A property can only have one value at a time (a list of property is one value), and if any code explicitly re-sets this value, the property binding is removed.
There is no way to create a property binding directly from imperative JavaScript code, although it is possible to use the Binding 元素。
Properties may bind to different types, but they are type-safe . That is, properties only allow you to assign 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 real volume: "four" //generates an error
Certain properties bind to more complex types such as other elements and objects.
Basic types such as int , real , and other Qt structures may be bound to properties. For a list of types, visit the QML 基本类型 文档。
id
特性
Each QML object may be given a special unique property called an
id
. No other object within the same QML component (see
QML 文档
) can have the same
id
value. QML objects may then access an object using the
id
特性。
Rectangle { id: container width: 100; height: 100 Rectangle { width: parent.width; height: parent.height } } Rectangle { width: container.width; height: container.height }
A component may readily access its parent's properties by using the
parent
特性。
Note that an
id
must begin with a lower-case letter or an underscore. The
id
cannot contain characters other than letters, numbers, underscores, and
JavaScript reserved words
.
Many properties bind to objects. For example, the
Item
element has a
状态
property that can bind to
State
elements. This type of property binding allows elements to carry additional non-children elements.
Item
's
过渡
property behaves in a similar way; it can bind to
Transition
元素。
Care must be taken when referring to the parent of an object property binding. Elements and components that are bound to properties are not necessarily set as children of the properties' component.
Rectangle { id: parentrectangle gradient: Gradient { //not a child of parentrectangle //generates a TypeError //Component.onCompleted: console.log(parent.width) } //child of parentrectangle Rectangle {property string name: "childrectangle"} //prints "childrectangle" Component.onCompleted: console.log(children[0].name) }
The code snippet has a
Gradient
element that attempts to print its parent's
width
value. However, the
Gradient
element is bound to the
gradient
property, not the
children
特性为
Rectangle
. As a result, the
Gradient
does not have the
Rectangle
as its parent. Printing the value of
parent.width
generates an error. Printing the
Rectangle
object's first child's
名称
将打印
childrectangle
because the second
Rectangle
is bound to the
children
特性。
更多信息有关
children
property, please read the
Default Properties
章节。
Certain objects provide additional properties by attaching properties to other objects. For example, the Keys element have properties that can attach to other QML objects to provide keyboard handling.
Component { id: listdelegate Text { text: "Hello" color: ListView.isCurrentItem ? "red" : "blue" } } ListView { delegate: listdelegate }
The element
ListView
provides the delegate,
listdelegate
, the property
isCurrentItem
as an attached property. The
ListView.isCurrentItem
attached property
provides highlight information to the delegate. Effectively, the
ListView
element attaches the
ListView.isCurrentItem
property to each delegate it creates.
附加信号处理程序 are similar to attached properties in that they attach to objects to provide additional functionality to objects. Two prominent elements, Component and Keys element provide 信号处理程序 as attached signal handlers.
Item { Keys.onPressed: console.log("Key Press Detected") Component.onCompleted: console.log("Completed initialization") }
Read the QML Signal and Handler Event System 和 Keyboard Focus in QML articles for more information.
Some properties may accept a binding to a list property, where more than one component can bind to the property. List properties allow multiple 状态 , 渐变 , and other components to bind to a single property.
Item { id: multistate states: [ State {name: "FETCH"}, State {name: "DECODE"}, State {name: "EXECUTE"} ] }
The list is enclosed in square brackets, with a comma separating the list elements. In cases where you are only assigning a single item to a list, you may omit the square brackets.
Item { id: monostate states: State {name: "RUNNING"} }
To access the list, use the
index
特性。
Component.onCompleted: console.log (multistate.states[0].name)
The snippet code simply prints the name of the first state,
FETCH
.
见 list type documentation for more details about list properties and their available operations.
In some cases properties form a logical group and use either the dot notation or group notation.
Grouped properties may be written both ways:
Text { //dot notation font.pixelSize: 12 font.bold: true } Text { //group notation font {pixelSize: 12; bold: true} }
In the element documentation grouped properties are shown using the dot notation.
Unlike a 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 . Read or write operations on the aliasing property results in a read or write operations on the aliased property, respectively.
A property alias declaration is similar to an ordinary property definition:
[default] property alias <name>: <alias reference>
As the aliasing property has the same type as the aliased property, an explicit type is omitted, and the special
alias
keyword is before the property name. Instead of a default value, a property alias has a compulsory alias reference. Accessing the aliasing property is similar to accessing a regular property. In addition, the optional
default
keyword indicates that the aliasing property is a
default property
.
property alias buttonLabel: label.text Text { id: label text: "empty label" }
When importing the component as a
Button
,
buttonlabel
is directly accessible through the
label
特性。
Button { id: textbutton buttonLabel: "Click Me!" }
此外,
id
property may also be aliased and referred outside the component.
Rectangle { property alias buttonImage: image Image {id: image} }
The
imagebutton
component has the ability to modify the child
Image
object and its properties.
Button { id: imagebutton buttonImage.source: "http://qt.nokia.com/logo.png" buttonLabel: buttonImage.source }
Using aliases, properties may be exposed to the top level component . Exposing properties to the top-level component allows components to have interfaces similar to Qt widgets.
Aliases are only activated once the component completes its initialization. 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 the component, however, aliasing properties appear as regular Qt properties and consequently can be used in alias references.
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 component has a
color
alias property, named the same as the built-in
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 component and refer to its
color
property will be referring to the alias rather than the ordinary
Rectangle::color
property. Internally, however, the
coloredrectangle
can correctly set its
color
property and refer to the actual defined property rather than the alias.
The TabWidget example uses aliases to reassign children to the ListView , creating a tab effect.
When imported, QML components will bind declared children to their designated
default properties
. The optional
default
attribute specifies a property as the
default property
. For example, the State element's default property is its
changes
特性。
PropertyChanges
elements may simply be placed as the
状态
's children and they will be bound to the
changes
特性。
State { changes: [ PropertyChanges {}, PropertyChanges {} ] } State { PropertyChanges {} PropertyChanges {} }
Similarly, the
Item
element's default property is its
data
property. The
data
property manages Item's
children
and
resources
properties. This way, different data types may be placed as direct children of the
Item
.
Item { Text {} Rectangle {} Timer {} } Item { //without default property children: [ Text {}, Rectangle {} ] resources: [ Timer {} ] }
Reassigning a default property is useful when a component is reused. For example, the
TabWidget
example uses the
default
attribute to reassign children to the
ListView
, creating a tab effect.
In some advanced cases, it may be necessary to create bindings explicitly with the Binding 元素。
For example, to bind a property exposed from C++ (
system.brightness
) to a value written in QML (
slider.value
), you could use the
Binding
element as follows:
Binding { target: system property: "brightness" value: slider.value }
The PropertyChanges element is for setting property bindings within a State element to set a property binding.
Rectangle { id: rectangle states: State { name: "WARNING" PropertyChanges { target: rectangle color: warning.color } } }
The rectangle's
color
property will bind to the
warning
component's
color
property when its
state
is set to the
WARNING
状态。