- Qt 6.6
- Qt QML
- Defining Object Types through QML Documents
- Qt 6.6.3 Reference Documentation

# 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 manner through QML documents to suit the needs of individual QML applications. The standard Qt Quick module provides various types like Rectangle, Text and Image for building a QML application; beyond these, you can easily define your own QML types to be reused within your application. This ability to create your own types forms the building blocks of any QML application.

## Defining an Object Type with a QML File

### Naming Custom QML Object Types

To create an object type, a QML document should be placed into a text file named as <TypeName>.qml where <TypeName> is the desired name of the type. The type name has the following requirements:

- It must be comprised of alphanumeric characters or underscores.
- It must begin with an uppercase letter.

This document is then automatically recognized by the engine as a definition of a QML type. Additionally, a type defined in this manner is automatically made available to other QML files within the same local directory as the engine searches within the immediate directory when resolving QML type names.

Note: The QML engine does not automatically search remote directories this way. You have to add a qmldir file if your documents are loaded over the network. See Importing QML Document Directories.

### Custom QML Type Definition

For example, below is a document that declares a Rectangle with a child MouseArea. The document has been saved to file named `SquareButton.qml`:

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

Since the file is named `SquareButton.qml`, this can now be used as a type named `SquareButton` by any other QML file within the same directory. For example, if there was a `myapplication.qml` file in the same directory, it could refer to the `SquareButton` type:

     // myapplication.qml
     import QtQuick 2.0

     SquareButton {}

This creates a 100 x 100 red Rectangle with an inner MouseArea, as defined in `SquareButton.qml`. When this `myapplication.qml` document is loaded by the engine, it loads the SquareButton.qml document as a component and instantiates it to create a `SquareButton` object.

The `SquareButton` type encapsulates the tree of QML objects declared in `SquareButton.qml`. When the QML engine instantiates a `SquareButton` object from this type, it is instantiating an object from the Rectangle tree declared in `SquareButton.qml`.

Note: the letter case of the file name is significant on some (notably UNIX) filesystems. It is recommended the file name case matches the case of the desired QML type name exactly - for example, `Box.qml` and not `BoX.qml` - regardless of the platform to which the QML type will be deployed.

### Inline Components

Sometimes, it can be inconvenient to create a new file for a type, for instance 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, Component is an option. But if you want to declare properties with the component types, or if you want to use it in multiple files, `Component` is not an option. In that case, you can use inline components. Inline components declare a new component inside of a file. The syntax for that is

     component <component name> : BaseType {
         // declare properties and bindings here
     }

Inside the file which declares the inline component, the type can be referenced simply by its name.

     // Images.qml
     import QtQuick

     Item {
         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 has to be prefixed with the name of its containing component.

     // LabeledImageBox.qml
     import QtQuick

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

Note: Inline components don't share their scope with the component they are declared in. In the following example, when `A.MyInlineComponent` in file B.qml gets created, a ReferenceError will occur, as `root` does not exist as an id in B.qml. It is therefore advisable not to reference objects in an inline component which are not part of it.

     // A.qml
     import QtQuick

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

     Item {
         A.MyInlineComponent {}
     }

Note: Inline components cannot be nested.

### Importing Types Defined Outside the Current Directory

If `SquareButton.qml` was not in the same directory as `myapplication.qml`, the `SquareButton` type would need to be specifically made available through an import statement in `myapplication.qml`. It could be imported from a relative path on the file system, or as an installed module; see module for more details.

## Accessible Attributes of Custom Types

The root object definition in a .qml file defines the attributes that are available for a QML type. All properties, signals and methods that belong to this root object - whether they are custom declared, or come from the QML type of the root object - are externally accessible and can be read and modified for objects of this type.

For example, the root object type in the `SquareButton.qml` file above is Rectangle. This means any properties defined by the Rectangle type can be modified for a `SquareButton` object. The code below defines three `SquareButton` objects with customized values for some of the properties of the root Rectangle object of the `SquareButton` type:

     // application.qml
     import QtQuick 2.0

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

The attributes that are accessible to objects of the custom QML type include any custom properties, methods and signals that have additionally been defined for an object. For example, suppose the Rectangle in `SquareButton.qml` had been defined as follows, with additional 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 could make use of the `pressed` property, `buttonClicked` signal and `randomizeColor()` method that have been added to the root Rectangle:

     // application.qml
     import QtQuick 2.0

     SquareButton {
         id: squareButton

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

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

Note that any of the `id` values defined in `SquareButton.qml` are not accessible to `SquareButton` objects, as id values are only accessible from within the component scope in which a component is declared. The `SquareButton` object definition above cannot refer to `mouseArea` in order to refer to the MouseArea child, and if it had an `id` of `root` rather than `squareButton`, this would not conflict with the `id` of the same value for the root object defined in `SquareButton.qml` as the two would be declared within separate scopes.

## Pragmas

You can prepend global instructions to a QML document using the `pragma` keyword. The following pragmas are supported:

### Singleton

`pragma Singleton` declares the component defined in the QML document as singleton. Singletons are created only once per QML engine. In order to use a QML-declared singleton you also have to register it with its module. See qt_target_qml_sources for how to do this with CMake.

### ListPropertyAssignBehavior

With this pragma you can define how assignments to list properties shall be handled in components defined in the QML document. By default, assigning to a list property appends to the list. You can explicitly request this behavior using the value `Append`. Alternatively, you can request the contents of list properties to always be replaced using `Replace`, or replaced if the property is not the default property using `ReplaceIfNotDefault`. For example:

     pragma ListPropertyAssignBehavior: ReplaceIfNotDefault

The same declaration can also be given for C++-defined types. See QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE, and QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT

### ComponentBehavior

You may have multiple components defined in the same QML file. The root scope of the QML file is a component, and you may additionally have elements of type QQmlComponent, explicitly or implicitly created as properties, or inline components. Those components are nested. Each of the inner components is within one specific outer component. Most of the time, IDs defined in an outer component are accessible within all its nested inner components. You can, however, create elements from a component in any a different context, with different IDs available. Doing so breaks the assumption that outer IDs are available. Therefore, the engine and the QML tooling cannot generally know in advance what type, if any, such IDs will resolve to at run time.

With the ComponentBehavior pragma you can restrict all inner components defined in a file to only create objects within their original context. If a component is bound to its context, you can safely use IDs from outer components in the same file within the component. QML tooling will then assume the outer IDs with their specific types to be available.

In order to bind the components to their context specify the `Bound` argument:

     pragma ComponentBehavior: Bound

This implies that, in case of name clashes, IDs defined outside a bound component override local properties of objects created from the component. Otherwise it wouldn't actually be safe to use the IDs since later versions of a module might add more properties to the component. If the component is not bound, local properties override IDs defined outside the component, but not IDs defined inside the component.

The example below prints the r property of the ListView object with the id color, not the r property of the rectangle's color.

     pragma ComponentBehavior: Bound
     import QtQuick

     ListView {
         id: color
         property int r: 12
         model: 1
         delegate: Rectangle {
             Component.onCompleted: console.log(color.r)
         }
     }

The default value of `ComponentBehavior` is `Unbound`. You can also specify it explicitly. In a future version of Qt the default will change to `Bound`.

Delegate components bound to their context don't receive their own private contexts on instantiation. This means that model data can only be passed via required properties in this case. Passing model data via context properties will not work. This concerns delegates to e.g. Instantiator, Repeater, ListView, TableView, GridView, TreeView and in general anything that uses DelegateModel internally.

For example, the following will not work:

     pragma ComponentBehavior: Bound
     import QtQuick

     ListView {
         delegate: Rectangle {
             color: model.myColor
         }
     }

The `delegate` property of ListView is a component. Therefore, a Component is implicitly created around the Rectangle here. That component is bound to its context. It doesn't receive the context property `model` provided by ListView. To make it work, you'd have to write it this way:

     pragma ComponentBehavior: Bound
     import QtQuick

     ListView {
         delegate: Rectangle {
             required property color myColor
             color: myColor
         }
     }

You can nest components in a QML file. The pragma holds for all components in the file, no matter how deeply nested.

### FunctionSignatureBehavior

With this pragma you can change the way type annotations on functions are handled. By default the interpreter and JIT ignore type annotations, but the QML script compiler enforces them when compiling to C++.

Specifying `Enforced` as value makes sure the type annotations are always enforced. The resulting type coercions increase the overhead of calling typed JavaScript functions.

Specifying `Ignored` as value makes the QML script compiler ignore any JavaScript functions when compiling the document to C++. This means less code is compiled to C++ ahead of time, and more code has to be interpreted or JIT-compiled.

### ValueTypeBehavior

With this pragma you can change the way value types and sequences are handled.

Usually lower case names cannot be type names in JavaScript code. This is a problem because value type names are lower case. You can specify `Addressable` as value for this pragma to change this. If `Addressable` is specified a JavaScript can be explicitly coerced to a specific, named, value type. This is done using the `as` operator, like you would do with object types. Furthermore, you can also check for value types using the `instanceof` operator:

     pragma ValueTypeBehavior: Addressable
     import QtQml

     QtObject {
         property var a
         property real b: (a as rect).x
         property bool c: a instanceof rect

         property var rect // inaccessible. "rect" is a type name.
     }

If the type does not match, casting returns `undefined`. `instanceof` only checks for inheritance, not for all possible type coercions. So, for example, a QRect is not a `rect` value type since `rect` is QRectF in C++, and therefore not related by inheritance. With `as` you can cast to any type compatible via coercion.

Since `rect` in the above example is now a type name, it will shadow any properties called `rect`.

Explicitly casting to the desired type helps tooling. It can allow the Qt Quick Compiler generate efficient code where it otherwise would not be able to. You can use qmllint to find such occurrences.

There is also a `Inaddressable` value you can use to explicitly specify the default behavior.

Value types and sequences are generally treated as references. This means, if you retrieve a value type instance from a property into a local value, and then change the local value, the original property is also changed. Furthermore, if you write the original property explicitly, the local value is also updated. This behavior is rather unintuitive in many places, and you should not rely on it. The `Copy` and `Reference` values for the `ValueTypeBehavior` pragma are experimental options to change this behavior. You should not use them. Specifying `Copy` causes all value types to be treated as actual copies. Specifying `Reference` explicitly states the default behavior.

Rather than using `Copy` you should explicitly re-load references to value types and sequences any time they can have been affected by side effects. Side effects can happen whenever you call a function or imperatively set a property. qmllint provides guidance on this. For example, in the following code the variable `f` is affected by side effects after writing `width`. This is because there may be a binding in a derived type or in a `Binding` element that updates `font` when `width` is changed.

     import QtQuick
     Text {
         function a() : real {
             var f = font;
             width = f.pixelSize;
             return f.pointSize;
         }
     }

In order to address this, you can avoid holding `f` across the write operation on `width`:

     import QtQuick
     Text {
         function a() : real {
             var f = font;
             width = f.pixelSize;
             f = font;
             return f.pointSize;
         }
     }

This, in turn can be shortened to:

     import QtQuick
     Text {
         function a() : real {
             width = font.pixelSize;
             return font.pointSize;
         }
     }

You might assume that re-retrieving the `font` property is costly, but actually the QML engine automatically refreshes value type references each time you read from them. So this is not more expensive than the first version, but a clearer way to express the same operations.

See also Type annotations and assertions and Type annotations and assertions.