Изложете QList‹QObject *› йерархията на QML

В момента съм в ситуация, че имам QList с MyClass, включително списък QList.

За да покажа тази списъчна йерархия, искам да осигуря Repeater в ListView.

Опитах това с QStringList и работи добре (вижте некоментираните редове по-долу). Когато се опитам да направя това с моя QList, не мога да осъществя достъп до name-property на MySubClass. Вместо това се показва свойството име на MyClass.

ГРЕШЕН изход:

Object 1
Object 1
Object 1
Object 2

Правилният изход трябва да бъде:

Object 1
SubObject 1
SubObject 2
Object 2

РЕДАКТИРАНЕ: 08.12.2014 Разбрах защо подсписъкът не работи. Просто трябваше да заменя един ред в делегата на под-ListView (име -> modelData.name).

Ето моят код:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QList>
#include <QDebug>

#include "myclass.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    /* create simple stringlist */
    QStringList dataList;
    dataList << "Data 1"
         << "Data 2"
         << "Data 3";

    /* create more complex QObject List */
    MySubClass *mySubObject = NULL;
    QList<QObject *> mySubList;

    mySubObject = new MySubClass;
    mySubObject->setName("SubObject 1");
    mySubList.append(mySubObject);

    mySubObject = new MySubClass;
    mySubObject->setName("SubObject 2");
    mySubList.append(mySubObject);

    /* create object list */
    MyClass *myObject = NULL;
    QList<QObject *> myList;

    myObject = new MyClass;
    myObject->setName("Object 1");
    myObject->setDataList(dataList);
    myObject->setObjectList(mySubList);
    myList.append(myObject);

    myObject = new MyClass;
    myObject->setName("Object 2");
    myObject->setDataList(dataList);
    myList.append(myObject);

    qDebug () << myList.size();

    myObject = NULL;

    /* start engine and expose object list */
    QQmlApplicationEngine engine;

    QQmlContext *myContext = engine.rootContext();
    myContext->setContextProperty("myObjectList", QVariant::fromValue(myList));

    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec();
}

MyClass.h

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QObject>
#include <QStringList>

#include "mysubclass.h"

class MyClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY (QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY (QStringList dataList READ dataList WRITE setDataList NOTIFY dataListChanged)
    Q_PROPERTY (QList<QObject *> objectList READ objectList WRITE setObjectList NOTIFY objectListChanged)
public:
    inline MyClass(QObject *parent = 0) : QObject(parent) {}
    inline ~MyClass() {}

    QString name() const
    {
        return m_name;
    }

    QStringList dataList() const
    {
        return m_dataList;
    }

    QList<QObject *> objectList() const
    {
        return m_objectList;
    }

public slots:
    void setName(QString arg)
    {
        if (m_name != arg) {
            m_name = arg;
            emit nameChanged(arg);
        }
    }

    void setDataList(QStringList arg)
    {
        if (m_dataList != arg) {
            m_dataList = arg;
            emit dataListChanged(arg);
        }
    }

    void setObjectList(QList<QObject *> arg)
    {
        if (m_objectList != arg) {
            m_objectList = arg;
            emit objectListChanged(arg);
        }
    }

signals:
    void nameChanged(QString arg);
    void dataListChanged(QStringList arg);

    void objectListChanged(QList<QObject *> arg);

private:
    QString m_name;
    QStringList m_dataList;

    QList<QObject *> m_objectList;
};

#endif // MYCLASS_H

MySubClass.h

#ifndef MYSUBCLASS_H
#define MYSUBCLASS_H

#include <QObject>
#include <QString>

class MySubClass : public QObject
{
    Q_OBJECT
    Q_PROPERTY (QString name READ name WRITE setName NOTIFY nameChanged)

public:
    inline MySubClass(QObject *parent = 0) : QObject(parent) {}
    inline ~MySubClass() {}

    QString name() const
    {
        return m_name;
    }
public slots:
    void setName(QString arg)
    {
        if (m_name != arg) {
            m_name = arg;
            emit nameChanged(arg);
        }
    }
signals:
    void nameChanged(QString arg);

private:
    QString m_name;
};

#endif // MYSUBCLASS_H

main.qml

import QtQuick 2.2
import QtQuick.Window 2.1

Window {
    visible: true
    width: 360
    height: 360

    ListView  {
        id: view
        anchors.fill: parent

        model: myObjectList

        delegate: Item {
            width: parent.width
            height: col.height
            Column {
                id: col
                Text {
                    id: nameLabel
                    text: name
                }

                Repeater {
                    id: dataView
//                    model: dataList
                    model: objectList
                    delegate: Text {
                        id: dataLabel
//                        text: modelData
                        // text: name
                          /* Here's the fix!!! (dunno why, but it works) */
                          text: modelData.name
                    }
                }
            }
        }
    }
}

person SGbo    schedule 05.12.2014    source източник
comment
stackoverflow.com/questions/35160909/   -  person dtech    schedule 03.07.2018


Отговори (2)


За излагане на QML списъци на типове, извлечени от QObject, трябва да се използва QQmlListProperty вместо QList<T> като тип свойство

MyClass.h:

Q_PROPERTY (QQmlListProperty<MySubClass> objectList READ getMySubClassList NOTIFY objectListChanged)

public:
   QQmlListProperty<MySubClass> getMySubClassList() {
      return QQmlListProperty<MySubClass>(this, 0, &MyClass::countMySubClassList, &MyClass::atMySubClassList);
   }
   static int countMySubClassList(QQmlListProperty<MySubClass> *property) {
      MyClass *m = qobject_cast<MyClass *>(property->object);
      return m->m_objectList.size();
   }
   static MySubClass *atMySubClassList(QQmlListProperty<MySubClass> *property, int index) {
      MyClass *m = qobject_cast<MyClass *>(property->object);
      return m->m_objectList[index];
   }
private:
   QList<MySubClass *> m_objectList

Освен това трябва да регистрирате MySubClass тип в системата QML, като използвате qmlRegisterUncreatableType

qmlRegisterUncreatableType<MySubClass,1>("project.mySubClass",1,0,"mySubClass","error message");
person Meefte    schedule 05.12.2014
comment
Благодаря, внедрих QQmlListProperty и изглежда работи. - Това е първият път, когато използвам QList вместо QAbstractListModel и за мен изглежда, че QQmlListProperty е много по-мощен от QAbstractListModel. Можете ли да обясните това? - person SGbo; 05.12.2014
comment
@Quperman Като модел QAbstractItemModel е много по-мощно, просто и гъвкаво решение. Можете да използвате QQmlListProperty като модел, ако искате да изложите прост кратък const списък. В друг случай QAbstractItemModel би бил за предпочитане. - person Meefte; 06.12.2014

Опитайте се да добавите Q_DECLARE_METATYPE(MySubClass*) след дефиницията на клас, в моя случай QList работи правилно, а, и предадох QObjectList като свойство

person Masha Kalinicheva    schedule 07.12.2017