Qt/QML如何从QAbstractListModel的虚拟数据方法中返回QList<T>集合

3

我希望能够总结一下需要做什么。我有一个DataObject类,它有以下成员:

QString first;QString last;QList<SubObject*> m_sublist; 

我将使用QAbstractListModel进行翻译。我可以引用listview的第一个和最后一个,但是我无法引用像m_sublist [0] .lesson 这样的内容。它会给我一个错误,如下所示:

无法读取未定义的属性“ lesson”。

我的代码: dataobject.h
        class SubObject :public QObject
    {
        Q_OBJECT


    public:
        SubObject(const QString &lesson,QObject *parent = 0);
        const QString lesson;

    private:


    //    bool operator==(const SubObject*  &other) const {
    //           return other->lesson == lesson;
    //    }

    };

    class DataObject :public QObject{

        Q_OBJECT
    public:
    DataObject(const QString &firstName,
                const QString &lastName,
                const QList<SubObject*>   &sublist);


    QString first;
    QString last;
    QList<SubObject*> m_sublist;
    };

simplelistmodel.h

    class SimpleListModel : public QAbstractListModel {
        Q_OBJECT
    public:
        SimpleListModel(QObject *parent=0);
        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
        int rowCount(const QModelIndex &parent = QModelIndex()) const;
        QHash<int,QByteArray> roleNames() const { return  m_roleNames; }



    private:
    // Q_DISABLE_COPY(SimpleListModel);

        QList<DataObject*> m_items;
        static const int FirstNameRole;
        static const int LastNameRole;
        static const int SubListRole;
    QHash<int, QByteArray> m_roleNames;
    };

simplelistmodel.cpp

        const int SimpleListModel::FirstNameRole = Qt::UserRole + 1;
    const int SimpleListModel::LastNameRole = Qt::UserRole + 2;
    const int SimpleListModel::SubListRole = Qt::UserRole + 3;


    SimpleListModel::SimpleListModel(QObject *parent) :
            QAbstractListModel(parent) {
        // Create dummy data for the list

        QList<SubObject*> mysublist;
        mysublist.append(new SubObject("MAT"));
        mysublist.append(new SubObject("FEN"));


        DataObject *first = new DataObject(QString("Arthur"), QString("Dent"),mysublist);
        DataObject *second = new DataObject(QString("Ford"), QString("Prefect"),mysublist);
        DataObject *third = new DataObject(QString("Zaphod"), QString("Beeblebrox"),mysublist);
        m_items.append(first);
        m_items.append(second);
        m_items.append(third);



    // m_roleNames = SimpleListModel::roleNames();
    m_roleNames.insert(FirstNameRole, QByteArray("firstName"));
    m_roleNames.insert(LastNameRole, QByteArray("lastName"));
    m_roleNames.insert(SubListRole, QByteArray("subList"));


    }

    int SimpleListModel::rowCount(const QModelIndex &) const {
    return m_items.size();
    }

    QVariant SimpleListModel::data(const QModelIndex &index,
                                                int role) const {
        if (!index.isValid())
            return QVariant(); // Return Null variant if index is invalid
        if (index.row() > (m_items.size()-1) )
            return QVariant();

        DataObject *dobj = m_items.at(index.row());
        switch (role) {
        case Qt::DisplayRole: // The default display role now displays the first name as well
        case FirstNameRole:
            return QVariant::fromValue(dobj->first);
        case LastNameRole:
            return QVariant::fromValue(dobj->last);
        case SubListRole:
            return QVariant::fromValue(dobj->m_sublist);

        default:
            return QVariant();
        }
    }

main.cpp

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

        QGuiApplication app(argc, argv);

        QQmlApplicationEngine engine;
        SimpleListModel model;


        QQmlContext *classContext = engine.rootContext();
        classContext->setContextProperty("absmodel",&model);

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

        return app.exec(); }

myuiscript.qml

        import QtQuick 2.0
    import QtQuick.Window 2.0
    Window {
        id: bgRect
        width: 200
        height: 200
            color: "black"
            visible: true

            ListView {
                id: myListView
                anchors.fill: parent
                delegate: myDelegate
                model: absmodel

            }
            Component {
    id: myDelegate
            Item {
    width: 200
            height: 40
            Rectangle {
                anchors.fill: parent
                    anchors.margins: 2
                    radius: 5
                    color: "lightsteelblue"
                    Row {
                        anchors.verticalCenter: parent.verticalCenter
                            Text {

    text: firstName
            color: "black"
            font.bold: true
                            }
                        Text {
    text: subList[0].lesson
            color: "black"
                        }
                    }
            }
            }
            }


    }

我找不到任何解决方案。虚拟数据模型返回单个类型的对象。FirsName是一个字符串。我无法像这样引用listview委托:firstName(rolename)。同样,LastName被引用为lastName(rolename)。但是我无法像这样引用subList(roleNames)sublist[0].lesson

我的目标非常简单。我想通过使用rolename将单个类型(int,QString ....)引用为委托中的文本。我无法使用rolename(subList[0].lesson)将集合type(QList<SubObject*>)引用为委托中的文本。如何实现?


如果 m_sublist 是一个 QList<SubObject*>,那么为什么你要像这样访问它:m_sublist[0].lesson 而不是 m_sublist[0]->lesson - Sergei Tachenov
@SergeyTachenov,在 QML 方面,你能否编写像 -> notations 这样的代码? - Kevin yudo
DataObject 在 QML 中是否为已注册类型? - folibis
1个回答

2
让我们逐步解决这个问题。QML中的这一行text: subList[0].lesson产生了错误消息。

TypeError:无法读取未定义的属性“lesson”

这意味着subList [0]是一个未定义的对象,QML引擎无法从该对象读取任何属性,包括lesson。实际上,从模型返回的subList是一个明确定义的QList<SubObject *>对象,但subList [0]不是因为QList<SubObject *>不是一个QML列表。要正确地将列表从C++传递到QML,请返回QVariantList而不是QList
//class DataObject
DataObject(const QString &firstName,
            const QString &lastName,
            const QVariantList &sublist);
QVariantList    m_sublist; //use QVariantList instead of QList<SubObject*>

//---
//SimpleListModel::SimpleListModel
QVariantList mysublist; //use QVariantList instead of QList<SubObject*>
mysublist.append(QVariant::fromValue(new SubObject("MAT", this))); //remember parent
mysublist.append(QVariant::fromValue(new SubObject("FEN", this)));
//...

现在,可以在QML中访问subList[0],但无法访问subList[0].lesson。要访问C++类中的属性,请使用Q_PROPERTY宏显式定义该属性。
class SubObject :public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString lesson READ getLesson NOTIFY lessonChanged)

public:
    SubObject(const QString &lesson,QObject *parent = 0):
        QObject(parent), m_lesson(lesson){;}
    QString getLesson() const {return m_lesson;}

signals:
    void lessonChanged();

private:
    QString m_lesson;
};

现在QML代码可以正常工作了。


1
一个 QList<SubOject*> 在 QML 中不是一个列表,但是一个 QList<QObject*> 是。 - GrecKo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接