【问题标题】:Expose QList<QObject *> hierarchy to QML将 QList<QObject *> 层次结构暴露给 QML
【发布时间】:2014-12-05 09:01:28
【问题描述】:

我目前的情况是,我有一个带有 MyClass 的 QList 还包括一个列表 QList。

为了显示这个列表层次结构,我想在 ListView 中提供一个中继器。

我用 QStringList 试过这个,它工作正常(见下面未注释的行)。当我尝试使用我的 QList 执行此操作时,我无法访问 MySubClass 的名称属性。而是显示 MyClass 的名称属性。

错误的输出:

Object 1
Object 1
Object 1
Object 2

正确的输出应该是:

Object 1
SubObject 1
SubObject 2
Object 2

编辑:08.12.2014 我发现了为什么子列表不起作用。我只需要在 sub-ListView (name -> modelData.name) 的委托中替换一行。

这是我的代码:

ma​​in.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

ma​​in.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
                    }
                }
            }
        }
    }
}

【问题讨论】:

标签: c++ qml qobject qlist


【解决方案1】:

为了公开 QObject 派生类型的 QML 列表,应该使用 QQmlListProperty 而不是 QList&lt;T&gt; 作为属性类型

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

另外,你应该在QML系统中注册MySubClass类型,使用qmlRegisterUncreatableType

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

【讨论】:

  • 谢谢,我实现了 QQmlListProperty,它似乎可以工作。 - 这是我第一次使用 QList 而不是 QAbstractListModel,对我来说,似乎 QQmlListProperty 比 QAbstractListModel 强大得多。你能解释一下吗?
  • @Quperman 作为模型,QAbstractItemModel 是更强大、更简单、更灵活的解决方案。如果要公开简单的短 const 列表,可以使用 QQmlListProperty 作为模型。在其他情况下,最好使用 QAbstractItemModel。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多