How to create dynamic QML objects in JavaScript

How to create dynamic QML objects in JavaScript

1. Dynamically create objects

There are two ways to create objects dynamically from JavaScript:

  • Call Qt.createComponent() to dynamically create a Component object
  • Create an object from a QML string using Qt.createQmlObject()

Although dynamically created objects can be used like other objects, they do not have ids in QML.

1.1. Dynamically create components

You can call its createObject() method to create an instance of the component. This function can accept two parameters:

The first is the parent object of the new object. The parent object can be a graphical object (ie, of type Item) or a non-graphical object (ie, of type QtObject or C++ QObject). Only graphics objects with a graphics parent are rendered onto Qt Quick visual canvas. If you wish to set the parent later, you can safely pass null to this function.
The second is optional and is a map of property-value pairs that defines the initial values ​​of any properties of the object. The property value specified by this parameter is applied to the object before object creation is completed, avoiding binding errors that can occur when specific properties must be initialized to enable binding of other properties. Also, the performance benefit is small compared to defining property values ​​and bindings after object creation.
Example.

Sprite.qml It defines a simple QML component:

import QtQuick 2.0
 
Rectangle { width: 80; height: 50; color: "red" }


main.qml imports a componentCreation.js JavaScript file, which creates the Sprite object:

import QtQuick 2.0
import "componentCreation.js" as MyScript
 
Rectangle 
{
    id: appWindow
    width: 300; height: 300
 
    Component.onCompleted: MyScript.createSpriteObjects();
}


componentCreation.js

var component;
var sprite;
 
function createSpriteObjects() 
{
    component = Qt.createComponent("Sprite.qml");
    if (component.status == Component.Ready)
        finishCreation();
    else
        component.statusChanged.connect(finishCreation);
}
 
function finishCreation() 
{
    if (component.status == Component.Ready) 
    {
        sprite = component.createObject(appWindow, {x: 100, y: 100});
        if (sprite == null) 
        {
            console.log("Error creating object");
        }
    } 
    else if (component.status == Component.Error) 
    {
        console.log("Error loading component:", component.errorString());
    }
}


When using files with relative paths, the paths should be relative to the file executing Qt.createComponent() .

It is also possible to instantiate components without blocking via the incu bateObject() function.

1.2. Creating objects from QML strings

QML objects can be created from a QML string using the Qt.createQmlObject() function, as shown in the following example:

const newObject = Qt.createQmlObject(`
    import QtQuick 2.0
    Rectangle 
    {
        color: "red"
        width: 20
        height: 20
    }
    `,
    parentItem,
    "myDynamicSnippet"
);


  • The first argument is the QML string to create.
  • The second argument is the parent object of the new object. The same semantics of the parent argument as for components apply to createQmlObject() .
  • The third argument is the file path associated with the new object; this is used for error reporting.

If the QML string uses a relative path to the file import, the path should be relative to the file defining the parent object (the second argument to the method).

When building a static QML application, the QML files are scanned to detect import dependencies. This way, all necessary plugins and resources are resolved at compile time. However, this only considers explicit import statements (those at the top of a QML file), not import statements contained in string literals. To support static builds, users need to ensure that QML files that use Qt.createQmlObject() explicitly include all necessary imports at the top of the file (including inside string literals).

2. Dynamically delete objects

In many user interfaces, it is sufficient to set the opacity of a visual object to 0 or to move the visual object off the screen instead of removing it. However, if there are a large number of dynamically created objects, deleting unused objects may yield valuable performance benefits.

Please note: Objects created dynamically by convenience QML object factories (such as Loaders and Repeaters) should never be manually deleted. Additionally, you should avoid deleting objects that you did not dynamically create yourself.

Items can be deleted using destroy() method. This method has an optional parameter (defaults to 0) that specifies the approximate delay (in milliseconds) before the object is destroyed.

Example. application.qml creates five instances of the SelfDestroyingRect.qml component. Each instance runs a NumberAnimation and when the animation is complete, it destroys itself by calling destroy() on its root object:

application.qml

import QtQuick 2.0
 
Item 
{
    id: container
    width: 500; height: 100
 
    Component.onCompleted: 
    {
        var component = Qt.createComponent("SelfDestroyingRect.qml");
        for (var i=0; i<5; i++) 
        {
            var object = component.createObject(container);
            object.x = (object.width + 10) * i;
        }
    }
}


SelfDestroyingRect.qml

import QtQuick 2.0
 
Rectangle 
{
    id: rect
    width: 80; height: 80
    color: "red"
 
    NumberAnimation on opacity 
    {
        to: 0
        duration: 1000
 
        onRunningChanged: 
        {
            if (!running) 
            {
                console.log("Destroying...")
                rect.destroy();
            }
        }
    }
}
 

Alternatively, application.qml can destroy the created object by calling object.destroy() .

Please note: It is safe to call destroy() on objects within this object. The object is not destroyed the instant destroy() is called, but rather it is cleaned up sometime between the end of the script block and the next frame (unless a non-zero delay is specified).

Also note that if the SelfDestroyingRect instance is created statically like this:

Item 
{
    SelfDestroyingRect 
    {
        // ...
    }
}


This will cause errors because an object can only be dynamically destroyed if it was dynamically created.

Objects created with Qt.createQmlObject() can be destroyed similarly using destroy():

const newObject = Qt.createQmlObject(`
    import QtQuick 2.0
    Rectangle 
    {
        color: "red"
        width: 20
        height: 20
    }
    `,
    parentItem,
    "myDynamicSnippet"
);
newObject.destroy(1000);

This is the end of this article about how to create dynamic QML objects in JavaScript . For more information about how to create dynamic QML objects in JavaScript, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Implementation of QT QML element layout

<<:  How to get the dynamic number of remaining words in textarea

>>:  How to remove inline styles defined by the style attribute (element.style)

Recommend

Detailed introduction to the MySQL installation tutorial under Windows

Table of contents 1. Some concepts you need to un...

Detailed explanation of zabbix executing scripts or instructions on remote hosts

Scenario Requirements 1. We can use the script fu...

Solution to the Docker container being unable to access the host port

I recently encountered a problem at work. The doc...

The reason why MySQL uses B+ tree as its underlying data structure

We all know that the underlying data structure of...

How to Change Colors and Themes in Vim on Linux

Vim is a text editor that we use very often in Li...

How to set up automatic daily database backup in Linux

This article takes Centos7.6 system and Oracle11g...

In-depth understanding of Vue's data responsiveness

Table of contents 1. ES syntax getter and setter ...

Example of how to create a local user in mysql and grant database permissions

Preface When you install MySQL, you usually creat...

Example of how to identify the user using a linux Bash script

It is often necessary to run commands with sudo i...

Example of horizontal arrangement of li tags in HTMl

Most navigation bars are arranged horizontally as...

18 killer JavaScript one-liners

Preface JavaScript continues to grow and prosper ...

vue+el-upload realizes dynamic upload of multiple files

vue+el-upload multiple files dynamic upload, for ...

One question to understand multiple parameters of sort command in Linux

The sort command is very commonly used, but it al...