如何在QML中访问C++对象的列表属性

How to access list property of C++ object in QML

本文关键字:对象 列表 属性 C++ 访问 QML      更新时间:2023-10-16

我已经开始学习Qt 5,并且在某一点上被卡住了很长时间。

我有两节课。ScoreHandler处理ScoreRecord列表。我在C++中创建了这两个类,并将ScoreHandler的一个实例设置为上下文属性。现在,在QML中,我可以分配模型,但代理无法查看ScoreRecord的属性。我必须在某个地方注册吗?请帮帮我。

记分记录.h

class ScoreRecord : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(QString date READ date WRITE setDate NOTIFY dateChanged)
    Q_PROPERTY(QString score READ score WRITE setScore NOTIFY scoreChanged)
public:
    ScoreRecord(QObject *parent = 0);
    ScoreRecord(const QString& n, const QString &d, const QString &s, QObject *parent = 0);
    QString name() const;
    void setName(const QString &str);
    QString date() const;
    void setDate(const QString &str);
    QString score() const;
    void setScore(const QString &str);

signals:
    void nameChanged();
    void dateChanged();
    void scoreChanged();
public slots:
private:
    QString m_name;
    QString m_date;
    QString m_score;
};

记分员.h

class ScoreHandler : public QObject
{
    Q_OBJECT
private:
    const char* SCORE_TABLE_FILENAME;
    struct scoreRow {
        char name[128];
        char date[32];
        char score[16];
    };

public:
    explicit ScoreHandler(QObject *parent = 0);
    QList<ScoreRecord *> scoreList;
signals:
public slots:
    void SaveScore(const QString &name, const QString &date, const QString &score);
    void LoadScore();
};

main.c

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    ScoreHandler* scoreHandler = new ScoreHandler();
    QQmlContext* ctx = viewer.rootContext();
    ctx->setContextProperty("MyScoreModel", QVariant::fromValue(scoreHandler->scoreList));
    viewer.setMainQmlFile(QStringLiteral("qml/qmlListView/main.qml"));
    viewer.showExpanded();
    return app.exec();
}

QML文件

import QtQuick 2.0
Rectangle {
    width: 360
    height: 360
    ListView {
        width: 100; height: 100
        anchors.fill: parent
        model: MyScoreModel
        delegate: Text {
            text: name
        }
    }
}

请有人解释一下,为什么下面的代码有效?原因是什么?

main.c

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    ScoreHandler* scoreHandler = new ScoreHandler();
    QList<QObject *> scoreList;
    scoreList.append(new ScoreRecord("Jmeno1", "datum1", "score1"));
    scoreList.append(new ScoreRecord("Jmeno2", "datum2", "score2"));
    scoreList.append(new ScoreRecord("Jmeno3", "datum3", "score3"));
    QQmlContext* ctx = viewer.rootContext();
    ctx->setContextProperty("MyScoreModel", QVariant::fromValue(scoreList));
    viewer.setMainQmlFile(QStringLiteral("qml/qmlListView/main.qml"));
    viewer.showExpanded();
    return app.exec();
}

我相信有一种更干净的方法。您需要在ScoreHandler上定义一个属性scoreList:

Q_PROPERTY(QQmlListProperty<ScoreRecord> scoreList READ scoreList)

还有一个保存ScoreRecord指针的私有变量:

QListrongcoreRecords;

然后您需要实现访问器方法:

// ScoreHandler.h
QQmlListProperty<ScoreRecord> scoreList();
// ScoreHandler.cpp
QQmlListProperty<ScoreRecord> ScoreHandler::scoreList()
{
    return QQmlListProperty<ScoreRecord>(this, _scoreRecords);
}

然后您可以从qml访问它。

QtCreator上有一个例子。它被称为扩展QML-对象和列表属性类型示例

我坚信

ctx->setContextProperty("MyScoreModel", QVariant::fromValue(scoreHandler->scoreList));

执行当前列表的副本,该列表在给定的示例中为空,并且在修改scoreList时不会更新。问题文档说:

注意:视图无法知道QList已更改。如果QList发生变化,则需要重置模型,方法是再次调用QQmlContext::setContextProperty()。

如果您需要真实的数据模型,请从QAbstractListModel派生并实现必要的覆盖:data(...)rowCount()count属性roleNames()

最后一个示例之所以有效,是因为它将静态列表分配给上下文变量。与JavaScript中相同:

[{name: Jmeno1, date: datum1, score: score1},
{name: Jmeno2, date: datum3, score: score2},
{name: Jmeno3, date: datum3, score: score3}]

Nuno Santos的回答很好,我还指出了您可能需要的两个重要修改:

请注意,ScoreRecord必须在QML类型的系统中注册,例如:qmlRegisterType<ScoreRecord>("com.mycompany.database", 1, 0, "ScoreRecord");

如果ScoreRecord在命名空间中,则必须定义如下属性:

Q_PROPERTY(QQmlListProperty<myNamespace::ScoreRecord> scoreList READ scoreList)

请注意,如果ScoreRecord在命名空间中,则可能需要像这样声明Q_PROPERTY。

Q_PROPERTY(QQmlListProperty<myNamespace::ScoreRecord> scoreList READ scoreList)