从 QML 访问 C++ QLists

2022-01-19 00:00:00 qt5 qtquick2 qml c++ qlist

如果我有 C++ 中的内容列表,如何将其公开给 QML(在 Qt5/QtQuick 2 中)?似乎 QML 只能理解 QObject 派生类,这是一个问题,因为 QObject 不能放入 QList 或复制.我该怎么做:

If I've got a list of things in C++, how do I expose that to QML (in Qt5 / QtQuick 2)? It seems like QML can only understand QObject-derived classes, which is an issue because QObjects can't be put in a QList or copied. How do I do this:

struct Thing
{
    int size;
    QString name;
};

class ThingManager : public QObject
{
    Q_OBJECT

    // These macros support QtQuick, in case we one day want to use it to make a slick
    // interface (when QML desktop components are released).
    Q_PROPERTY(QList<Thing> things READ things NOTIFY thingssChanged)

public:
    // ...
    QList<Thing> things() const;

    // ...

};

这样我就可以在 QML 中做这样的事情:?

So that I can do something like this in QML:?

var a = thingManager.things[0].name;

推荐答案

在获得更多 QML 经验后,我发现拥有事物列表的最佳方式是使用 QAbstractListModel.

After more experience with QML I've found the best way to have lists of things is with a QAbstractListModel.

您使您的 ThingQObject 派生,因此它可以存储在 QVariant 中(在注册之后).然后您可以将实际的 Thing 作为模型项返回.您可以在 Repeater 中以 model.display.a_property_of_thing 的形式访问它.列表长度以 model.count 的形式提供.

You make your Thing derive from QObject so it can be stored in a QVariant (after registering it). Then you can return the actual Thing as the model item. You can access it in a Repeater as model.display.a_property_of_thing. The list length is available as model.count.

这有以下优点和缺点:

  1. 快速 - 它不会复制整个列表来访问一个元素.
  2. 您可以轻松获取列表更改的动画(添加、重新排列和删除项目).
  3. 在 QML 中很容易使用.
  4. 为了使动画能够正常工作,每当您更改列表时,您都必须做一些稍微有点古怪的簿记(beginInsertRows() 等)

...

class Things : public QObject
{
...
};

Q_DECLARE_METATYPE(Thing*)

class ThingList : public QAbstractListModel
{
    Q_OBJECT
    
public:
    explicit ThingList(QObject *parent = 0);
    ~ThingList();

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

public slots:

    // Extra function to get the thing easily from outside Repeaters.
    Thing* thing(int idx);

private:
    QList<Thing*> mThings;
};

int ThingList::rowCount(const QModelIndex& parent) const
{
    return mThings.size();
}

QVariant ThingList::data(const QModelIndex& index, int role) const
{
    int i = index.row();
    if (i < 0 || i >= mThings.size())
        return QVariant(QVariant::Invalid);

    return QVariant::fromValue(mThings[i]);
}

Thing* ThingList::thing(int idx)
{
    if (idx < 0 || idx >= mThings.size())
        return nullptr;

    return mThings[idx];
}

相关文章