Dynamic instantiation of QML objects?

You could simply:

import QtQuick 2.0

Rectangle {
    id: root
    height: 500
    width: 500

    property string sc: 'import QtQuick 2.0; Rectangle {width: 20; height: 20; color: "red"; Component.onCompleted: {x = Math.random() * parent.width; y = Math.random() * parent.height;}}'

    Component.onCompleted: {
        for (var i = 0; i < 10; ++i) Qt.createQmlObject(sc, root, 'obj' + i);
    }
}

This code will create the specified number of rectangles and position them randomly over the parent rectangle.

If generating the position in C++ is a necessity, you will have to create a custom C++ element, here is a basic example:

class Positioner : public QObject
{
    Q_OBJECT
public:
    explicit Positioner(QObject *parent = 0) : QObject(parent) {}

public slots:
    QPointF getPosition() {
        return QPoint(qrand() % 500, qrand() % 500);
    }    
};

Register it in main.cpp:

qmlRegisterType<Positioner>("TestComponent", 1, 0, "Positioner");

And finally use it, this time we use the Positioner’s getPosition() C++ slot:

    import QtQuick 2.0
    import TestComponent 1.0

    Rectangle {
        id: root
        height: 500
        width: 500

        Positioner {id: myPositioner}

        property string sc: 'import QtQuick 2.0; Rectangle {width: 20; height: 20; color: "red"; Component.onCompleted: {var pos = myPositioner.getPosition(); x = pos.x; y = pos.y;}}'

        Component.onCompleted: {
            for (var i = 0; i < 10; ++i) Qt.createQmlObject(sc, root, 'obj' + i);
        }
    }

You can also use an existing QML file instead of a string, which is a little more convenient, since you get autocomplete. That would be your TestItem component and just for fun, its instances will delete themselves when clicked:

import QtQuick 2.0

Rectangle {
    width: 100
    height: 100
    color: "black"

    MouseArea {
        anchors.fill: parent
        onClicked: parent.destroy()
    }

    Component.onCompleted: {
        var pos = myPositioner.getPosition()
        x = pos.x
        y = pos.y
    }
}

And in your main QML file you instantiate it:

var component = Qt.createComponent("TestItem.qml")
component.createObject(root)

In case you don’t want to instantiate a Positioner in QML and instead instantiate and use a single object in QML, you can do the following (in main.cpp):

Positioner p;
view.rootContext()->setContextProperty("sPositioner", &p);

And use in QML:

var pos = sPositioner.getPosition()

Leave a Comment