QML Reference Guide 02: QML Object Attribute 2

 

Property alias

An attribute alias is an attribute that holds a reference to another attribute. Unlike ordinary attribute definitions that allocate new unique storage space for attributes, attribute aliases connect newly declared attributes (called alias attributes) as direct references to existing attributes (alias attributes).

The attribute alias declaration looks like a normal attribute definition, except that it requires the alias keyword instead of the attribute type, and the right side of the attribute declaration must be a valid alias reference:

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

Unlike ordinary attributes, aliases have the following restrictions:

· It can only refer to objects or properties of objects within the scope of the type where the alias is declared.

· It cannot contain arbitrary JavaScript expressions

· It cannot reference objects declared outside its type range.

· The alias reference is not selectable, unlike ordinary properties with optional default values; the alias reference must be provided when the alias is first declared.

· It cannot refer to additional attributes.

• It can not reference a deep degree of attributes within the hierarchy of 3 or greater . The following code does not work:

property alias color: myItem.myRect.border.color

Item {
id: myItem
property Rectangle myRect
}

 

However, you can use up to two levels of attribute aliases.

 

property alias color: rectangle.border.color
Rectangle {
id: rectangle}

 

For example, the following is the type of Button with the alias property of buttonText, which is connected to the object of the Text subtext object:

// Button.qml
import QtQuick 2.0
Rectangle {
property alias buttonText: textItem.text

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

Text { id: textItem }}

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

Button { buttonText: "Click Me" }

 

Here, modifying buttonText directly modifies the value of textItem.text; it does not change other values, and then updates textItem.text. If buttonText is not an alias, changing its value will not actually change the displayed text at all, because the attribute binding is not bidirectional: if buttonText changes textItem.text, the value will have changed, but not vice versa.

Notes on property aliases

The alias can only be activated after the component is fully initialized. When an uninitialized alias is referenced, an error will be generated. Similarly, aliasing the alias attribute will also cause 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"

However, when importing a QML object type with an attribute alias in the root object, the attribute is displayed as a regular Qt attribute, so it can be used in the alias reference.

The alias attribute may have the same name as the existing attribute, thereby effectively overwriting the existing attribute. For example, the following QML types have a color alias attribute with the same name as the built-in Rectangle :: color attribute:

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 uses this type and references its color attribute will refer to the alias, not the ordinary Rectangle :: color attribute. However, internally, the rectangle can correctly set its color attribute and reference the actually defined attribute, not an alias.

Property aliases and types

Attribute aliases cannot have explicit type specifications. The type of attribute alias is the declared type of the attribute or object it refers to. Therefore, if you create an alias for an object referenced by id and use other attributes declared inline, you cannot access these additional attributes through the alias:

// MyItem.qml 
Item { 
property alias inner: innerItem 

Item { 
id: innerItem 
property int extraProperty 
}} 
You cannot initialize inner.extraProperty from outside this component, because inner is just an Item: 
// main.qmlMyItem { 
inner.extraProperty: 5 / / fails}

However, if you use a dedicated .qml file to extract the internal objects into a separate component, you can instantiate the component and use all its properties through aliases:

// MainItem.qml
Item {
// Now you can access inner.extraProperty, as inner is now an ExtraItem
property alias inner: innerItem

ExtraItem {
id: innerItem
}
}

// ExtraItem.qml
Item {
property int extraProperty
}

Default attributes

The object definition can have a default attribute. The default attribute is an attribute assigned a value if an object is declared in the definition of another object but not declared as the value of a specific attribute.

Using the optional default keyword to declare an attribute will mark it as the default attribute. For example, suppose there is a file MyLabel.qml someText with default properties:

// MyLabel.qml
import QtQuick 2.0
Text {
default property var someText

text: "Hello, " + someText.text
}

The someText value can be assigned to it in the MyLabel object definition as follows:

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

Same as the following:

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

However, because the someText property has been marked as the default property, there is no need to explicitly assign the Text object to this property.

You will notice that you can add child objects to any Item-based type without having to explicitly add them to the children property. This is because the default attribute of an item is its data attribute, and any item added to this list will be automatically added to the child objects in its list.

The default attributes are useful for reassigning items to items. See the TabWidget example, which uses default properties to automatically reassign the children of the TabWidget to the children of the internal ListView.

Read-only attribute

Object declarations can use the readonly keyword to define read-only attributes with the following syntax:

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

A value must be assigned to the read-only attribute during initialization. After the read-only attribute is initialized, it can no longer be assigned a value, either from imperative code or other means.

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

Item { 
readonly property int someNumber: 10 

Component.onCompleted: someNumber = 20 // doesn't work, causes an error} 
Note: The read-only property cannot also be the default property.

Property modifier object

An attribute may have an attribute value modifier object associated with it. The syntax for declaring an instance of an attribute modifier type associated with a specific attribute is as follows:

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

It is important to note that the above syntax is actually an object declaration that will instantiate objects that act on pre-existing properties.

Some attribute modifier types may only apply to specific attribute types, but this is not enforced by the language. For example, the type QtQuick provided by NumberAnimation will only animate properties of numeric types (such as int or real). Trying to use NumberAnimation with non-numeric properties will not cause an error, but will not animate non-numeric properties. The behavior of an attribute modifier type when it is associated with a specific attribute type is defined by its implementation.

Signal properties

The signal is a notification from an object that indicates that certain events have occurred: for example, the property has changed, the animation has started or stopped, or the image has been downloaded. In the mouse area type, for example, there is a user click signal emitted when the mouse area is clicked.

Whenever a specific signal is issued, the object can be notified through a signal handler. Use on <Signal> syntax to declare the signal handler, where <Signal> is the signal name, 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 JavaScript code block to be executed when the signal handler is called.

For example, the following onClicked signal handler is declared in the MouseArea object definition and is called when the MouseArea is clicked, causing the console message to be printed:

import QtQuick 2.0
Item {
width: 100; height: 100

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

Define signal properties

You can define a signal for a type in C ++ by registering Q_SIGNAL of a class and then registering it in the QML type system. Alternatively, you can use the following syntax to define a custom signal of the object type in the object declaration of the QML document:

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

It is an error to try to declare two signals or methods with the same name in the same type block. However, new signals may reuse the names of existing signals in type. (This should be done with caution, as existing signals may be hidden and become difficult to access.)

These are three examples of signal declarations:

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

If the signal has no parameters, the "()" bracket is optional. If you use parameters, you must declare the parameter type, such as the string and var parameters of the above signal actionPerformed. The allowed parameter types are the same as those listed under "Define property properties" on this page.

To signal, call it as a method. When a signal is issued, any related signal handler will be called, and the handler can use the defined signal parameter name to access the corresponding parameter.

Property change signal

The QML type also provides a built-in property change signal, which is emitted whenever the property value changes, as previously described in the property properties section. For more information on why these signals are useful and how to use them, see the upcoming section on property change signal handlers.

Signal handler properties

The signal handler is a special method attribute, as long as the associated signal is emitted, the QML engine will call the implementation of the method. Adding a signal to an object definition in QML will automatically add an associated signal handler to the object definition, which is empty by default. The customer can provide an implementation to implement the program logic.

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

// SquareButton.qml
Rectangle {
id: root

signal activated(real xPosition, real yPosition)
signal deactivated

property int side: 100
width: side; height: side

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

These signals can be received by any object in another QML file in the same directory of SquareButton, where the implementation of the signal handler is provided by the client:

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

For more detailed information about the use of signals, see Signal and handler event systems.

Property change signal handler

The signal handler of the property change signal adopts the syntax form of on <Property> Changed, where <Property> is the name of the property, with the first letter capitalized. For example, although TextInput type documents do not record the textChanged signal, because TextInput has a text property, the signal is implicitly available, so as long as this property changes, you can write the signal handler to be called:

import QtQuick 2.0
TextInput {
text: "Change this!"

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

Method attributes

Object type methods are functions that can be called to perform certain processing or trigger other events. You can connect a method to a signal so that the method is automatically called when the signal is issued. For more details, see Signal and Handler Event System.

Define method attributes

You can define a method for a type in C ++ by marking a function of a class and then using Q_INVOKABLE to register the class in the QML type system or register it as Q_SLOT of the class. Alternatively, you can use the following syntax to add a custom method to the object declaration in the QML document:

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

Methods can be added to QML types to define independent reusable JavaScript code blocks. These methods can be called in internal or external objects.

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

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

The following is a Rectangle, with a calculateHeight () method, which is called when a value is assigned to height.

import QtQuick 2.0
Rectangle {
    id: rect
    function calculateHeight() {
      return rect.width / 2;
    } 
   width: 100
    height: calculateHeight()
}

If the method has parameters, you can access them by name within the method. Below, when you click MouseArea, it will call the moveTo () method, and then the method can refer to receiving newX to newY parameters and parameters to reposition the text:

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

Additional attributes and additional signal handlers

Additional attributes and additional signal handlers are mechanisms that enable an object to annotate with other attributes or signal handlers, and additional attributes or signal handlers are not available for the object. In particular, they allow objects to access properties or signals that are specifically related to a single object.

QML type implementation can choose to create additional types with specific properties and signals in C ++. You can then create instances of this type and attach them to specific objects at runtime, allowing those objects to access the attributes and signals of the additional types. Access the attributes and corresponding signal handlers by prefixing them with additional types of names.

References to additional attributes and handlers have the following syntax:

<AttachingType>.<propertyName>

<AttachingType>.on<SignalName>

For example, the type of ListView has an additional property ListView.isCurrentItem, which can be used in the ListView of each delegate object. Each individual delegate object can use it to determine whether it is the currently selected item in the view:

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 additional type is ListView and the related property is isCurrentItem, so the additional property is called ListView.isCurrentItem.

The additional signal handlers are referenced in the same way. For example, after the component creation process is complete, Component.onCompleted is usually used to attach some signal handlers to execute some JavaScript code. In the following example, once the ListModel is completely created, Component.onCompleted will automatically call its signal handler to fill the model:

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 additional type is Component and the type has a complete signal, the additional signal handler is called Component.onCompleted.

Points to note about accessing additional properties and signal handlers

A common mistake is to assume that additional properties and signal handlers can be directly accessed from the children of objects that have these properties attached. This is not the case. Instances of additional types are only attached to specific objects, not to the object and all its sub-objects.

For example, below is a modified version of the previous example that contains attachment attributes. This time, the commission is a project, and the colored rectangle is a sub-item of the project:

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 only attached to the root delegate object, not its child objects. Because Rectangle is a child of the delegate, not the delegate itself, it cannot access the isCurrentItem additional property ListView.isCurrentItem in the form. Therefore, the rectangle should be accessed by isCurrentItem through the root delegate:

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

The delegateItem.ListView.isCurrentItem now correctly references the additional properties delegated by isCurrentItem.

Enumeration properties

Enumeration provides a fixed set of naming options. You can declare them in QML using the enum keyword:

// MyText.qmlText {
    enum TextType {
        Normal,
        Heading
    }}

As shown above, the enumeration type (eg TextType) and value (eg Normal) must start with a capital letter.

Pass <Type>. <EnumerationType>. <Value> or reference value <Type>. <Value>.

// MyText.qmlText {
    enum TextType {
        Normal,
        Heading
    }
    property int textType: MyText.TextType.Normal
    font.bold: textType == MyText.TextType.Heading
    font.pixelSize: textType == MyText.TextType.Heading ? 24 : 12}

For more information about the use of enumerations in QML, see the QML basic types enumeration documentation.

Qt 5.10 introduced the ability to declare enumerations in QML.

 

Published 52 original articles · praised 4 · 50,000+ views

Guess you like

Origin blog.csdn.net/caridle/article/details/105693923