Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Troubles passing a list<> from Qml to C++

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

Scheduled Pinned Locked Moved QML and Qt Quick
2 Posts 2 Posters 1.2k Views
  • 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 Offline
    C Offline
    cscooper
    wrote on last edited by
    #1

    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
    0
    • C Offline
      C Offline
      chrisadams
      wrote on last edited by
      #2

      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
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved