从QML访问C++ QLists

Tim*_*mmm 27 c++ qlist qml qt5 qtquick2

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

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;

    // ...

};
Run Code Online (Sandbox Code Playgroud)

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

var a = thingManager.things[0].name;
Run Code Online (Sandbox Code Playgroud)

Dic*_*son 24

或者,您可以使用QVariantList(QList<QVariant>),它将在传递给QML时自动更改为JavaScript数组,并且可以从C++和QML读取和写入

  • `QVariant`几乎可以包含"一切",包括另一个`QVariantList`或`QVariantMap`. (3认同)

eat*_*ens 22

我在尝试修复类似问题时遇到了这个问题,我想在CML中使用C++代码作为模型源.TheBootroo给出的答案指出了我正确的方向,但并没有完全适合我.我没有足够的声誉直接回答他(但我做了他的回答).

我使用Qt 5.0.0我发现这个链接非常有帮助

应该如下更改ThingManager的定义

class ThingManager : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<QObject*> things READ getThings NOTIFY thingsChanged)

public:
    QList<QObject*> getThings () const { return m_things; }

signals:
    void thingsChanged ();

private:
    QList<QObject*> m_things;
};
Run Code Online (Sandbox Code Playgroud)

请注意,我将getThings的返回类型更改为QList <QObject*>.如果没有这个改变,Qt会警告它"无法处理未注册的数据类型'QList <Thing*>'".

在QML代码中,Thing的属性可以通过模型作为model.modelData.size和model.modelData.name来访问.

  • 您可以使用 qmlRegisterType&lt;Thing&gt;("com.yourapp",1,0,"Thing") 函数注册类型,并且不需要使用 QObject。您的“事物”必须声明为类。 (2认同)

Tim*_*mmm 9

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

你可以Thing从中得到QObject它,因此它可以存储在QVariant(注册后)中.然后您可以返回实际Thing作为模型项.你可以在Repeateras中访问它model.display.a_property_of_thing.列表长度可用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 >= mPorts.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];
}
Run Code Online (Sandbox Code Playgroud)


Tim*_*mmm 5

我找到了答案(我认为,未经测试): QQmlListProperty

示例中有一些用途,例如qtdeclarative/examples/quick/tutorials/gettingStartedQml/filedialog/directory.*:

不幸的是,目前您只能拥有只读列表。