If we want to use a list of custom C++ objects in QML we can use QQmlListProperty
While registering it in QML we need to specify a function that QML will read the list with.
The documentation states that for fully functional list we need to use this function:
QQmlListProperty::QQmlListProperty(QObject *object, void *data, AppendFunction append,
CountFunction count, AtFunction at, ClearFunction clear)
Here is example of how do I write it in C++:
classwithlist.h
#ifndef CLASSWITHLIST_H
#define CLASSWITHLIST_H
#include <QObject>
#include <QQmlListProperty>
#include "element.h"
class Element;
class ClassWithList : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Element> elements READ getElements NOTIFY elementsChanged)
public:
explicit ClassWithList(QObject *parent = 0);
QQmlListProperty<Element> getElements();
void appendElements(QQmlListProperty<Element> *list, Element *e);
static int elementsCount(QQmlListProperty<Element> *list);
static Element* elementsAt(QQmlListProperty<Element> *list, int i);
static void elementsClear(QQmlListProperty<Element> *list);
signals:
void elementsChanged(QQmlListProperty<Element>);
private:
QList<Element *> m_elements;
};
#endif // CLASSWITHLIST_H
classwithlist.cpp
#include "classwithlist.h"
ClassWithList::ClassWithList(QObject *parent) : QObject(parent)
{
}
QQmlListProperty<Element> ClassWithList::getElements()
{
return QQmlListProperty<Element>(this, m_elements, &appendElements,&elementsCount,&elementsAt,&elementsClear);
}
void ClassWithList::appendElements(QQmlListProperty<Element> *list, Element *e)
{
ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
if (cwl && e) {
cwl->m_elements.append(e);
}
}
int ClassWithList::elementsCount(QQmlListProperty<Element> *list)
{
ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
if (cwl)
return cwl->m_elements.count();
return 0;
}
Element *ClassWithList::elementsAt(QQmlListProperty<Element> *list, int i)
{
ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
if (cwl)
return cwl->m_elements.at(i);
return 0;
}
void ClassWithList::elementsClear(QQmlListProperty<Element> *list)
{
ClassWithList *cwl = qobject_cast<ClassWithList*>(list->object);
if (cwl) {
cwl->m_elements.clear();
}
}
And after exposing the class to QML I have following code in QML
ClassWithList {
Component.onCompleted: {
console.log(elements.length) // works
console.log(elements[0]) // works
// elements.push() // does not work
// elements.append() // does not work
// elements.clear() // does not work
// elements.at() // does not work
}
}
Can I use functions that will add items to the list or clear it? As seen above I can use functions CountFunction
and AtFunction
by using .length
and brackets. Can I somehow use ClearFunction
and AppendFunction
too?
Maybe I cannot do this with QQmlListProperty
and I should use QAbstractListModel
?
EDIT: Due to changes in the list property interface, the answer below is no longer completly true. It is now possible to append objects by using push
(from the documentation linked below):
Values can be dynamically added to the list by using the push method, as if it were a JavaScript Array
Original answer below
You cannot append elements to or clear a QQmlListProperty
directly in QML. To edit QQmlListProperty
in QML, assign a new list to it.
According to QML list
documentation:
Any
QQmlListProperty
value passed into QML from C++ is automatically converted into alist
value, and vice-versa.Note that objects cannot be individually added to or removed from the list once created; to modify the contents of a list, it must be reassigned to a new list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With