简体   繁体   English

公开QList <QObject *> 到QML的层次结构

[英]Expose QList<QObject *> hierarchy to QML

I'm currently in the situation, that I have a QList with MyClass also including a list QList. 我目前处于这种情况,我有一个带有MyClass的QList,还包括一个列表QList。

To display this list-hierarchy I want to provide a Repeater within a ListView. 为了显示此列表层次结构,我想在ListView中提供一个Repeater。

I tried this with a QStringList and it works fine (see uncommented lines below). 我用QStringList进行了尝试,它工作正常(请参见下面的未注释行)。 When I try to do this with my QList I cannot access the name-property of MySubClass. 当我尝试使用QList进行此操作时,无法访问MySubClass的名称属性。 Instead the name-property of MyClass is shown. 而是显示MyClass的名称属性。

WRONG output: 错误输出:

Object 1
Object 1
Object 1
Object 2

Correct output should be: 正确的输出应为:

Object 1
SubObject 1
SubObject 2
Object 2

EDIT: 08.12.2014 I found out, why the sublist did not work. 编辑:08.12.2014我发现,为什么子列表不起作用。 I just had to replace one line in the delegate of the sub-ListView (name -> modelData.name). 我只需要替换子ListView的委托中的一行(名称-> modelData.name)。

Here's my code: 这是我的代码:

main.cpp 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 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 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 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
                    }
                }
            }
        }
    }
}

For exposing to QML lists of QObject-derived types, one should use QQmlListProperty rather than QList<T> as the property type 为了向QML派生QObject派生类型的列表,应该使用QQmlListProperty而不是QList<T>作为属性类型。

MyClass.h: 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

Also, you should register MySubClass type in the QML system, by using qmlRegisterUncreatableType 另外,您应该使用qmlRegisterUncreatableType在QML系统中注册MySubClass类型。

qmlRegisterUncreatableType<MySubClass,1>("project.mySubClass",1,0,"mySubClass","error message");

尝试在类定义之后添加Q_DECLARE_METATYPE(MySubClass*) ,在我的情况下,QList工作正常,啊,我将QObjectList作为属性传递

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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