将QList <qobject * =“”>层次结​​构公开给QML </qobject>

时间:2014-12-05 09:01:29

标签: c++ qml qobject qlist

我目前处于这种情况,我有一个带有MyClass的QList,还包括一个列表QList。

要显示此列表层次结构,我想在ListView中提供Repeater。

我尝试使用QStringList并且它工作正常(请参阅下面的未注释的行)。当我尝试使用我的QList执行此操作时,我无法访问MySubClass的name-property。而是显示MyClass的name-property。

错误的输出:

Object 1
Object 1
Object 1
Object 2

正确的输出应该是:

Object 1
SubObject 1
SubObject 2
Object 2

编辑:2014年12月8日 我发现,为什么子列表不起作用。我只需要替换子ListView的委托中的一行(name - &gt; 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
                    }
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:3)

为了公开QObject派生类型的QML列表,应该使用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

此外,您应该使用qmlRegisterUncreatableType

在QML系统中注册MySubClass类型
qmlRegisterUncreatableType<MySubClass,1>("project.mySubClass",1,0,"mySubClass","error message");

答案 1 :(得分:0)

尝试在类定义后添加$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl'] = array ( 'encodeSpURL_postProc' => array('user_encodeSpURL_postProc'), 'decodeSpURL_preProc' => array('user_decodeSpURL_preProc'), '_DEFAULT' => array ( 'init' => array ( 'enableCHashCache' => '1', 'appendMissingSlash' => 'ifNotFile', 'enableUrlDecodeCache' => '1', 'enableUrlEncodeCache' => '1' ), 'redirects' => array ( ), 'preVars' => array ( '0' => array ( 'GETvar' => 'no_cache', 'valueMap' => array ( 'nc' => '0' ), 'noMatch' => 'bypass', ), '1' => array ( 'GETvar' => 'L', 'valueMap' => array ( 'de' => '0', 'en' => '1', 'tr' => '2' ), 'noMatch' => 'bypass' ), ), 'pagePath' => array ( 'type' => 'user', 'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main', 'spaceCharacter' => '-', 'languageGetVar' => 'L', 'rootpage_id' => '1' ), 'fixedPostVars' => array ( ), 'postVarSets' => array ( '_DEFAULT' => array ( 'archive' => array ( '0' => array ( 'GETvar' => 'tx_ttnews[year]' ), '1' => array ( 'GETvar' => 'tx_ttnews[month]', 'valueMap' => array ( 'january' => '01', 'february' => '02', 'march' => '03', 'april' => '04', 'may' => '05', 'june' => '06', 'july' => '07', 'august' => '08', 'september' => '09', 'october' => '10', 'november' => '11', 'december' => '12' ), ), ), 'page' => array ( '0' => array ( 'GETvar' => 'tx_ttnews[pointer]' ), ), 'category' => array ( '0' => array ( 'GETvar' => 'tx_ttnews[cat]', 'lookUpTable' => array ( 'table' => 'tt_news_cat', 'id_field' => 'uid', 'alias_field' => 'title', 'addWhereClause' => ' AND NOT deleted', 'useUniqueCache' => '1', 'useUniqueCache_conf' => array ( 'strtolower' => '1', 'spaceCharacter' => '-' ), ), ), ), 'article' => array ( '0' => array ( 'GETvar' => 'tx_ttnews[tt_news]', 'lookUpTable' => array ( 'table' => 'tt_news', 'id_field' => 'uid', 'alias_field' => 'title', 'addWhereClause' => ' AND NOT deleted', 'useUniqueCache' => '1', 'useUniqueCache_conf' => array ( 'strtolower' => '1', 'spaceCharacter' => '-' ), ), ), '1' => array ( 'GETvar' => 'tx_ttnews[swords]' ), ), ), ), 'fileName' => array ( #'defaultToHTMLsuffixOnPrev' => '.html', #'acceptHTMLsuffix' => 1, 'index' => array ( 'rss.xml' => array ( 'keyValues' => array ( 'type' => '100' ), ), 'rss091.xml' => array ( 'keyValues' => array ( 'type' => '101' ), ), 'rdf.xml' => array ( 'keyValues' => array ( 'type' => '102' ), ), 'atom.xml' => array ( 'keyValues' => array ( 'type' => '103' ), ), 'sitemap.xml' => array ( 'keyValues' => array ( 'type' => '776' ), ), ), ), ) ); /* * All your other domain configuration goes here. Change your domain name * and domain root page id as per your need. * */ $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['domain.de'] = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['_DEFAULT']; $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['domain.de']['pagePath']['rootpage_id'] = '41'; // Change your sub-domain root page id $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['domain.eu'] = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['_DEFAULT']; $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['domain.eu']['pagePath']['rootpage_id'] = '51'; // Change your sub-domain root page id $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['domain.com.tr'] = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['_DEFAULT']; $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['domain.com.tr']['pagePath']['rootpage_id'] = '61'; // Change your sub-domain root page id ,在我的情况下,QList正常工作啊,我将QObjectList作为属性传递