简体   繁体   中英

Reading a QList<QPoint> in QML

I have the following class definition:

class PlaneGridQML : public QObject
{
    Q_OBJECT
    ........
    Q_INVOKABLE QList<QPoint> getPlanesPoints() {
        return m_PlaneGrid.getPlanesPoints();
    ......
}

In main I am making it available to the QML engine

PlaneGridQML pgq(10, 10, 3, false);
engine.rootContext()->setContextProperty("PlaneGrid",&pgq);

Then inside a QML Component I would like to do the following:

Connections {
    target: PlaneGrid
    onPlanesPointsChanged: {
        var pointsArray = PlaneGrid.getPlanesPoints()
        console.log(pointsArray[0].x)
    }
}

I am getting an error "Unknown method return type: QList" and obviously I cannot read pointsArray and display its first member. According to the Qt documentation QPoint can be directly transferred as a JS type. On the other hand QPoint does not derive from QObject .

Can anyone explain how can I list the elements of the array ( the QPoints ) in the JS function?

Yes, a QPoint will be auto converted to QML, and even a QList of certain objects will get auto converted to QML, but just because QList<int> works and QPoint work, it is not necessary mean that QList<QPoint> will also work.

This is the list of automatic types in a list that QML supports:

QList<int>
QList<qreal>
QList<bool>
QList<QString> and QStringList
QList<QUrl>
QVector<int>
QVector<qreal>
QVector<bool>

As you see, QPoint is not one of them.

Wrapping in a QObject would be a waste.

But do not despair. I suggest you declare QList<QPoint> * as a meta type, then you can wrap that in a QVariant to pass it as a opaque pointer to QML. Then, in your PlaneGridQML or another, single QObject derived type, you implement an interface to get the size of the list and individual points at a given index.

You basically implement a standalone accessor / manipulator for lists of points. And you are all set.

I also strongly recommend that you use QVector instead of QList in this scenario.

class PlaneGridQML : public QObject
{
    Q_OBJECT
    ........
    Q_INVOKABLE QPoint get(int i) { return planesPoints[i]; }
    ...
}
...
console.log(PlaneGrid.get(0).x)

If you only have one plane grid and one set of points, you don't even need to pass the opaque pointer to QML, you can just directly use the plane grid to get the size and individual elements via index. Easy peasy.

You can expose QPoint to QML, but not QList<QPoint> . I see three possible solutions to your problem:

  1. Add arguments to PlaneGridQML::planesPointsChanged signal. You cannot expose QList<QPoint> but you can send two variables of type QList<qreal> as the signal arguments. One list could hold x values and another y values.
  2. Implement int PlaneGridQML::getPlanesPointsCount() and QPoint PlaneGridQML::getPlanesPoint(int index) . So you have two functions - one which returns how many points there are, and second which return point for each index.
  3. Create a new class that will hold two variables ( planePointX , planePointY ) and return QQmlListProperty<NewClass> with PlaneGridQML::getPlanesPoints . However this approach is rather not a very good idea for your case (too complicated). More info .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM