Troubles passing a list<> from Qml to C++
-
I've got a Qml item I've defined (call it MyItem) and in Qml I'm constructing lists of these guys:
@property list<MyItem> items: [
MyItem { id: fred },
MyItem { id: george }
]@Then I've got a C++ class that looks something like this:
@class MyInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant stuff READ getStuff WRITE setStuff NOTIFY stuffChanged)
...
void setStuff(QVariant stuff)
{
m_var = stuff;
m_list = m_var.value<QQmlListReference>();
}QVariant m_var;
QQmlListReference m_list;
}@When I say (in Qml)
@theInfo.stuff = items@everything works fine - my C++ code gets the list of MyItem objects and can process them as I need.
The problem comes when I change to a new set of items:
@theInfo.stuff = differentItems@When the C++ code sets m_list to the new QQmlList, it destructs all of the objects in the old list. My Qml code clearly shows that "items" is now empty.
How can I, in my C++ code, view the list of MyItem objects created in Qml, without destroying them when I'm done with them?
Thanks,
Chris -
Hi,
I cannot reproduce your issue, using Qt 5.3
Here is my code:listprop.pro:
@
QT += qml quick
SOURCES += main.cpp
HEADERS += ListPropTest.h
FILES += test.qml
TARGET=listprop
@ListPropTest.h:
@
#ifndef LISTPROPTEST_H
#define LISTPROPTEST_H
#include <QObject>
#include <QVariant>
#include <QQmlListReference>
#include <QtDebug>class ListPropTest : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariant listRef READ listRef WRITE setListRef NOTIFY listRefChanged)public:
ListPropTest(QObject *parent = 0) : QObject(parent) {}Q_INVOKABLE void doTest(const QVariant &listprop) { m_listref = listprop.value<QQmlListReference>(); for (int i = m_listref.count() - 1; i >= 0; --i) { qDebug() << "CPP: new list: " << m_listref.at(i); } emit listRefChanged(); } QVariant listRef() const { return QVariant::fromValue<QQmlListReference>(m_listref); } void setListRef(const QVariant &listprop) { doTest(listprop); }
Q_SIGNALS:
void listRefChanged();private:
QQmlListReference m_listref;
};
#endif
@main.cpp:
@
#include <QtGui/QGuiApplication>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickView>
#include <qqml.h>
#include <QtDebug>#include "ListPropTest.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);QQuickView viewer; ListPropTest test; viewer.engine()->rootContext()->setContextProperty("listPropTest", &test); viewer.setSource(QStringLiteral("test.qml")); viewer.show(); return app.exec();
}
@test.qml
@
import QtQuick 2.0Item {
id: rootproperty list<QtObject> objectsA: [ QtObject { id: aOne; objectName: "aOne" }, QtObject { id: aTwo; objectName: "aTwo" } ] property list<QtObject> objectsB: [ QtObject { id: bOne; objectName: "bOne" }, QtObject { id: bTwo; objectName: "bTwo" } ] onObjectsAChanged: { console.log("ObjectsA Changed!") for (var a in objectsA) { console.log(objectsA[a]) } } onObjectsBChanged: { console.log("ObjectsB Changed!") for (var b in objectsB) { console.log(objectsB[b]) } } Timer { running: true interval: 2000 repeat: true property int triggerCount: 0 onTriggered: { triggerCount++ if (triggerCount == 1) { listPropTest.listRef = objectsA //or: listPropTest.doTest(objectsA) } else if (triggerCount == 2) { listPropTest.listRef = objectsB //or: listPropTest.doTest(objectsB) // check that objectsA is still valid, not cleared for (var a in objectsA) console.log("QML: old list: " + objectsA[a]) } else { // ensure that there was no delete-later style delayed deletion for (var a in objectsA) console.log("QML: old list: " + objectsA[a]) repeat = false; running = false; } } }
}
@After running for 6 seconds, the objects in the objectsA list remain valid and not deleted. Perhaps the object which you reference the list property from somehow goes out of scope or otherwise gets deleted, rendering the list property invalid?
Cheers,
Chris.