In this article, I show you how to use Javascript to dynamically produce graphics. We described dynamic QML production in the previous example “How to use QML to dynamically generate Components for our balloon game (2)”. Maybe that project is a little bit more duplicative, but let me illustrate it with some simple examples, just to make it a little bit more intuitive. See the article “Dynamic QML Object Creation from JavaScript” for more information.

\

1) Create our dynamic QML file

\

This file will be used to be dynamically produced by Javascript. This is a template, although the generated Object properties may be different each time.

\

dynamic-image.qml

\

Import QtQuick 2.0 Image {width: 400 height: 225 source: "images/image1.jpg" Image {id: overlay anchors. Fill: parent source: "images/image2.jpg" opacity: 0; Behavior on opacity { NumberAnimation { duration: 300 } } } MouseArea { anchors.fill: parent onClicked: { if (overlay.opacity === 0) overlay.opacity = 1; else overlay.opacity = 0; }}}Copy the code


\

This is a very simple QML file. It displays an image, and when we click on the image, the images in the overlay will cross and hide.

\

\

\

2) Create Javascript that dynamically produces QML objects

\

create-component.js

\

var component;

function createImageObject(x, y) {
    component = Qt.createComponent("dynamic-image.qml");
    if (component.status === Component.Ready || component.status === Component.Error)
        finishCreation(x, y);
    else
        component.statusChanged.connect(finishCreation);
}

function finishCreation(x, y) {
    if (component.status === Component.Ready)
    {
        var image = component.createObject(container, {"x": x, "y": y, width: 300, height:200});
        if (image == null)
            console.log("Error creating image");
    }
    else if (component.status === Component.Error)
        console.log("Error loading component:", component.errorString());
}
Copy the code


\

This file is used to dynamically produce the QML objects we need. The template it uses is the “dynamic-image.qml” template we used in the previous section. We can set its position parameters. Of course, we can also set its other properties. The “container” here is where we want the QML Object we want to produce to be placed, its “parent”.

\

\

3) Call Javascript in QML code to produce QML objects

\

Import QtQuick 2.0 import Ubuntu.Components 1.1 import "create-component.js" as ImageCreator /*! \brief MainView with a Label and Button elements. */ MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "dynamicqml.liu-xiao-guo" /* This property enables the application to change orientation when the device is rotated. The  default is false. */ //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false width: units.gu(60) height: units.gu(85) Page { id: root title: i18n.tr("dynamicqml") property int position: 0 Flickable { width: parent.width height: parent.height clip:true contentHeight: container.childrenRect.height Column { id: container anchors.centerIn: parent } } Row { anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.bottomMargin: units.gu(1) spacing: units.gu(1) Button { text: "Create New" onClicked: { ImageCreator.createImageObject(0, root.position); root.position += 200; }} Button {text: "Create from string" onClicked: {var newObject = qt. createQmlObject('import QtQuick 2.0; Image {source: "images/image3.jpg"; width: 300; height: 200}', container, "dynamicSnippet1"); newObject.x = 0; newObject.y = root.position; } } } Component.onCompleted: { ImageCreator.createImageObject(0, 0); root.position += 200 } } }Copy the code


\

In the code above:

\

Button { text: "Create New" onClicked: { ImageCreator.createImageObject(0, root.position); root.position += 200; }}Copy the code

\

This code is used to produce the QML objects we need and place them where we need them. As we explained in the previous section, we define a “container.” This is actually a layout manager for Column.

\

Alternatively, we can use code:

\

Button {text: "Create from string" onClicked: {var newObject = qt. createQmlObject('import QtQuick 2.0; Image {source: "images/image3.jpg"; width: 300; height: 200}', container, "dynamicSnippet1"); newObject.x = 0; newObject.y = root.position; }}Copy the code

Create our QML object as a string using Qt.createQMlobject. This is also a neat way to do it.

\

To run our app:

\


\

\

\

We can dynamically produce our QML objects using the buttons at the bottom of the screen.

\

\

4) Dynamic QML Object production management

\

We can destroy produced QML objects by using Destroy. To manage our object, we create a ListModel:

\

        ListModel {
            id: objectsModel
        }
Copy the code

We can add our generated object as follows:

\

 function itemAdded(obj, source) {
        objectsModel.append({"obj": obj, "source": source})
    }
Copy the code

Thus, whenever we create a new object, we also add it to it:

\

Row { anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.bottomMargin: units.gu(1) spacing: units.gu(1) Button { text: "Create New" onClicked: { var image = ImageCreator.createImageObject(0, root.position); itemAdded(image, "dynamic-image.qml"); root.position += 200; }}Copy the code

\

Finally, we can destroy all the dynamic-image.qml objects we created by doing the following.

\

Button { text: "Clear objects" onClicked: { while(objectsModel.count > 0) { objectsModel.get(0).obj.destroy(); objectsModel.remove(0); }}}Copy the code


    \

\

\

The image on the right above is the display after “Clear Objects” is pressed.

\

\

The entire project source at: github.com/liu-xiao-gu…

\