首页 > 解决方案 > 如何正确地将 C++ 模型链接到 QML 前端

问题描述

这是我的设置:

首先是模型类,它存储了一个指向数据类型的指针CompetitionsList。我们可以看到它在派生时实现了必要的基本功能QAbstractListModel,并且它使用QML_ELEMENT宏将模型暴露给 QML 类型系统:

class CompetitionsListModel : public QAbstractListModel
{
    Q_OBJECT
    Q_PROPERTY(CompetitionsList* list READ list WRITE setList)
    QML_ELEMENT

public:
    explicit CompetitionsListModel(QObject *parent = nullptr);

    enum {
        NameRole = Qt::ItemDataRole(),
        IdRole
    };

    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

    CompetitionsList *list() const;
    void setList(CompetitionsList *list);

    virtual QHash<int, QByteArray> roleNames() const;

private:
    CompetitionsList* m_list;  \\ <--- ptr to data
};

然后我们有数据类。这个类也是一个QML_ELEMENT,并且它有一个userid属性。这用于QVector<listItem>通过从 RESTful http 服务器请求数据来填充。

当数据添加preItemAppended()到. 然后将这些信号连接到模型,以通知模型它必须在列表中创建一个新行。这里的重要功能是,我将在下面解释。postItemAppended()QVector<listItem>populateCompetitions

struct listItem {
    QString competitionName;
    QString competitionId;
};

class CompetitionsList : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString userId READ getUserId WRITE setUserId)
    QML_ELEMENT

public:
    explicit CompetitionsList(QObject *parent = nullptr);
    void populateCompetitions(const QString& userId);
    QVector<listItem> items();
    QString getUserId() const;
    void setUserId(const QString &value);

signals:
    void preItemAppended();
    void postItemAppended();
    void errorPopulatingData();
private:
    QVector<listItem> m_competitions;
    QString userId;
};

populateCompetitions函数如下所示:

void CompetitionsList::populateCompetitions(const QString &userId)
{
    qDebug() << "initialising data";
    HttpClient* client = new HttpClient();
    client->getUserCompetitions(userId);

    connect(client, &HttpClient::getUserCompetitionsResult, [=](const QByteArray& reply){
        QJsonDocument _reply = QJsonDocument::fromJson(reply);

        if(_reply["data"].isNull()) {
            emit errorPopulatingData();
        }
        else {
            const QJsonArray competitions = _reply["data"]["competitions"].toArray();
            for(const QJsonValue& competition : competitions) {
                emit preItemAppended();

                listItem item{competition["competition-name"].toString(), competition["competition-id"].toString()};
                m_competitions.append(std::move(item));

                emit postItemAppended();
            }
        }
    });
}

它从数据库请求数据,然后将其存储在本地。

最后,将它们联系在一起的 QML 模型:

ListView {
        id: view
        implicitHeight: 1920
        implicitWidth: 1080
        clip: true

        model: CompetitionsListModel {
            list: CompetitionsList {
                id: compList
            }
            Component.onCompleted: { compList.userId = "6033f377257e8630ed13299e" } //<-- calls the populateCompetitions function
        }

        delegate: RowLayout {
            Text {
                text: qsTr(model.name + ":::" + model.id)
            }
        }
    }

我们可以看到它有一个ListView元素,有一个类型的模型CompetitionsListModel和一个类型的列表CompetitionsList。创建模型组件后,我们设置列表的 userId,然后调用该populateCompetitions函数设置模型要使用的数据,如上所示。

不幸的是,当我运行代码时,这没有任何意义。黑屏。纳达。我想知道是否有人根据提供的代码了解可能导致这种情况的原因。我已经做了这么久,它只是很好。

标签: qtqml

解决方案


我认为您需要在 CompetitionsListModel 上调用 qmlRegisterType 或 UncreatableType : https ://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterType


推荐阅读