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 QObject
s 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;
// ...
};
So that I can do something like this in QML:?
var a = thingManager.things[0].name;
After more experience with QML I've found the best way to have lists of things is with a QAbstractListModel
.
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
.
This has the following pros and cons:
beginInsertRows()
etc.)...
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];
}