6

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?

dtech
  • 47,916
  • 17
  • 112
  • 190
Knight of Ni
  • 1,780
  • 3
  • 20
  • 47

1 Answers1

17

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()
dtech
  • 47,916
  • 17
  • 112
  • 190
  • my question seems to be sketchy. by 'random' I meaned something which is irregular, not like ListView which defines a layout... In your example the Positioner is instantiated in QML. How can I write to Positioner from external C++ class, which exists before QML view? May the Positioner be singleton with static access? – Knight of Ni Apr 15 '13 at 00:52
  • Well, you don't want a list, you don't want a grid, you don't want random, then what exactly do you mean by irregular? – dtech Apr 15 '13 at 01:01
  • Added how to instantiate the `Positioner` in C++ and use in QML in the end of the answer. – dtech Apr 15 '13 at 01:13
  • Thank you so much :) This really opens my eyes. Especially the Qt.createQmlObject for dynamic QML instances creation. Your response is really comprehensive... – Knight of Ni Apr 15 '13 at 22:45
  • This is really a good and complete answer. I get some good information about exposing C++ logic output into QML. Thank you – S.M.Mousavi Jul 22 '14 at 08:52