qt - 如何正确地将 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
函数设置模型要使用的数据,如上所示。
不幸的是,当我运行代码时,这没有任何意义。黑屏。纳达。我想知道是否有人根据提供的代码了解可能导致这种情况的原因。我已经做了这么久,它只是很好。
解决方案
我认为您需要在 CompetitionsListModel 上调用 qmlRegisterType 或 UncreatableType : https ://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterType
推荐阅读
- c# - 如何为航点添加随机布尔标志?
- python - 选择圆用于 cv2 选择 (ROI)
- jenkins - 由于收到垃圾文本错误,无法在最新的 Jenkins 中启动 ssh 从属连接到 Redhat 7.9
- android - 如何将应用内购买订阅添加到 Android?
- sql - 搜索查询执行时间与总表行数无关
- mongodb - 如何从聚合 mongoDB 中获取结果?
- javascript - ReactJS:如何从 const 对象动态加载 SVG?
- python - 从树莓派3串口读取数据
- python - VS 代码:ModuleNotFoundError:没有名为“sklearn”的模块
- r - 拆分列的R代码是什么