Properties and Property Binding in QMLPropertiesQML components have properties that can be read and modified by other objects. In QML, properties serve many purposes but their main function is to hold to values. Values may be a basic type, 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. 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 BindingProperty 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: 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 Math. 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. Property Assignment versus Property BindingWhen 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 ":". 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 (unless explicitly assigned, see below). 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. Binding to JavaScript FunctionsThe property : value syntax for property binding is QML-specific and cannot be used in JavaScript. Instead, to bind a property from JavaScript, assign the result returned by the Qt.binding() function to the property. This will cause a binding assignment on the specified property. The following code correctly creates the binding in JavaScript rather than QML: Item { width: 100 Component.onCompleted: { height = Qt.binding(function() { return width * 2 }) } } When creating a property binding from JavaScript, QML allows the use of the this keyword to refer to the object to which the property binding will be assigned. This allows one to explicitly refer to a property within an object when there may be ambiguity about the exact property that should be used for the binding. For example, the Component.onCompleted handler below is defined within the scope of the Item, and references to width within this scope would refer to the Item's width, rather than that of the Rectangle. To bind the Rectangle's height to its own width, the function passed to Qt.binding() needs to explicitly refer to this.width rather than just 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 } } In this case, the function could also have referred to rect.width rather than this.width. Note that the value of this is not defined outside of its use in property binding. See QML JavaScript Restrictions for details. The Binding element provides more control for binding properties with JavaScript code. Types of PropertiesProperties may bind to different types, but they are 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 Property TypesBasic types such as int, real, and other Qt structures may be bound to properties. For a list of types, visit the QML Basic Types document. Elements and Objects as Property ValuesMany properties bind to objects. For example, the Item element has a states property that can bind to State elements. This type of property binding allows elements to carry additional non-children elements. Item's transitions property behaves in a similar way; it can bind to Transition elements. 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. 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 property of the 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 name will print childrectangle because the second Rectangle is bound to the children property. For more information about the children property, please read the Default Properties section. Attached PropertiesCertain 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. 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. Attached Signal HandlersAttached signal handlers 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 signal handlers as attached signal handlers. Read the QML Signal and Handler Event System and the Keyboard Focus in QML articles for more information. List propertiesSome properties may accept a binding to a list property, where more than one component can bind to the property. List properties allow multiple States, Gradients, and other components to bind to a single property. 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. To access the list, use the index property. The snippet code simply prints the name of the first state, FETCH. See the list type documentation for more details about list properties and their available operations. Grouped PropertiesIn some cases properties form a logical group and use either the dot notation or group notation. Grouped properties may be written both ways: In the element documentation grouped properties are shown using the dot notation. Property AliasesUnlike 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. When importing the component as a Button, the buttonlabel is directly accessible through the label property. In addition, the id property may also be aliased and referred outside the component. The imagebutton component has the ability to modify the child Image object and its properties. 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. Considerations for property aliasesAliases 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. 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 property: 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. Default PropertiesWhen 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 property. PropertyChanges elements may simply be placed as the State's children and they will be bound to the changes property. 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. 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. Using the Binding ElementIn some advanced cases, it may be necessary to create bindings explicitly with theBinding element. For example, to bind a property exposed from the declarative runtime or Qt object, such as the system.brightness property, to a value written in QML, you could use the Binding element as follows: Changing Property Values in StatesThe PropertyChanges element is for setting property bindings within a State element to set a property binding. The rectangle's color property will bind to the warning component's color property when its state is set to the WARNING state. |