Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Troubles passing a list<> from Qml to C++

    QML and Qt Quick
    2
    2
    1038
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      cscooper last edited by

      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

      1 Reply Last reply Reply Quote 0
      • C
        chrisadams last edited by

        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.0

        Item {
        id: root

        property 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.

        1 Reply Last reply Reply Quote 0
        • First post
          Last post