Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
738 views
in Technique[技术] by (71.8m points)

qt - Dynamic instantiation of QML objects?

I want to draw many Rectangular's inside a QML. The coordinates for Rectangulars (x,y) will be calculated inside C++, and need to be passed to QML.

I tried to look for ListView or Column or Row elements (with Repeater), but non of this seems to solve the problem, because the elements are arranged like in 'tables'... I faced the lack of information on the web examples on such case.

To be more specific:
1. How to pass many coordinates for my Rectangular's to QML? (what data structure)
2. What mechanism should I use to display them?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...