Defining object types through QML documents

One of the core features of QML is that it enables QML object types to be easily defined in a lightweight way through QML documents for reuse in your applications.

1, Defining object types using QML files

1.1 naming custom QML object types

To create an object type, place the QML document in a file named < typename > QML, where < typename > is the desired type name. The type name has the following requirements:

  • Must consist of alphanumeric characters or underscores.
  • Must start with a capital letter.

The document is then automatically recognized by the engine as a definition of the QML type. In addition, when resolving QML type names, when the engine searches in the direct directory, the types defined in this way are automatically available to other QML files in the same directory.

1.2. User defined QML type definitions

For example, the following document declares a Rectangle with a child MouseArea. The document has been saved to a file named squarebutton QML file:

// SquareButton.qml
import QtQuick 2.0

Rectangle 
{
    property int side: 100
    width: side; height: side
    color: "red"

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

Because the file name is SquareButton QML, so it can now be used as a type called SquareButton by any other QML file in the same directory. For example, if there is a myapplication. In the same directory QML file, which can reference the SquareButton type:

// myapplication.qml
import QtQuick 2.0

SquareButton {}

When this myapplication When the QML document is loaded by the engine, it will square button The QML document is loaded as a component and instantiated to create a SquareButton object.

Note: the case of file names is important on some (especially UNIX) file systems. It is recommended that the case of the file name exactly match the case of the desired QML type name - for example, box QML instead of box QML - regardless of the platform to which the QML type will be deployed.

1.3. Inline components

Sometimes it can be inconvenient to create a new file for a type, such as when reusing a small delegate in multiple views.

If you don't actually need to expose the type, but only need to create an instance, you can use Component.

However, if you want to declare a property with a component type, or if you want to use it in multiple files, you can use inline components in this case. Inline component declares a new component in a file. The syntax is:

component <component name> : BaseType {
    // Properties and bindings are declared here
}

In the file that declares the inline component, you can simply refer to the type by its name.

// Images.qml
import QtQuick 2.15

Item 
{
    //Define inline components
    component LabeledImage: Column 
    {
        property alias source: image.source
        property alias caption: text.text

        Image 
        {
            id: image
            width: 50
            height: 50
        }
        Text 
        {
            id: text
            font.bold: true
        }
    }

    Row
    {
        LabeledImage 
        {
            id: before
            source: "before.png"
            caption: "Before"
        }
        LabeledImage 
        {
            id: after
            source: "after.png"
            caption: "After"
        }
    }
    property LabeledImage selectedImage: before
}

In other files, it must be prefixed with the name of the component it contains.

// LabeledImageBox.qml
import QtQuick 2.15

Rectangle 
{
    property alias caption: image.caption
    property alias source: image.source
    border.width: 2
    border.color: "black"
    Images.LabeledImage 
    {
        id: image
    }
}

Note: inline components do not share their scope with the component that declares them. In the following example, when A.MyInlineComponent in the file B.qml is created, a ReferenceError will occur because root does not exist as an id in B.qml. Therefore, it is recommended not to reference objects in an inline component that do not belong to it.

// A.qml
import QtQuick 2.15

Item 
{
    id: root
    property string message: "From A"
    component MyInlineComponent : Item 
    {
        Component.onCompleted: console.log(root.message)
    }
}

// B.qml
import QtQuick 2.15

Item 
{
    A.MyInlineComponent {}
}

Note: inline components cannot be nested.

2, Accessible properties of custom types

. The root object definition in the QML file defines the properties that can be used for QML types. All properties, signals and methods belonging to the root object, whether they are custom declared or QML types from the root object, can be accessed externally, and can be read and modified for this type of object.

For example, the square button The root object type in the QML file is Rectangle. This means that any property defined by the Rectangle type can be modified for the SquareButton object.

Modify the built-in properties:

// application.qml
import QtQuick 2.0

Column 
{
    SquareButton { side: 50 }
    SquareButton { x: 50; color: "blue" }
    SquareButton { radius: 10 }
}

To access custom properties, methods, and signals:

// SquareButton.qml
import QtQuick 2.0

Rectangle 
{
    id: root

    property bool pressed: mouseArea.pressed

    signal buttonClicked(real xPos, real yPos)

    function randomizeColor() 
    {
        root.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1)
    }

    property int side: 100
    width: side; height: side
    color: "red"

    MouseArea 
    {
        id: mouseArea
        anchors.fill: parent
        onClicked: (mouse)=> root.buttonClicked(mouse.x, mouse.y)
    }
}

Any SquareButton object can use the press property added to the root Rectangle, the buttonClicked signal, and the randomizeColor() method:

// application.qml
import QtQuick 2.0

SquareButton 
{
    id: squareButton

    onButtonClicked: (xPos, yPos)=> 
    {
        console.log("Clicked", xPos, yPos)
        randomizeColor()
    }

    Text { text: squareButton.pressed ? "Down" : "Up" }
}

SquareButton. Any id value defined in QML cannot be accessed by the squarebutton object, because the id value can only be accessed from the scope of the declared component.

Keywords: qml

Added by jfdutcher on Sat, 11 Dec 2021 13:32:02 +0200