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. passing a list of custom objects to QML
Forum Update on Monday, May 27th 2025

passing a list of custom objects to QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
5 Posts 2 Posters 3.6k 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.
  • J Offline
    J Offline
    jacraig
    wrote on last edited by
    #1

    First let me tell you what my overall goal is: to pass a list (vector, array or whatever) of custom C++ objects into QML. I've been able to do this successfully (as in it compiles, runs and gives the result I want), but it's possible I'm doing something that I shouldn't. Also it's not clear to me why my solution works and not another one. Here is some code (omitting includes and some other stuff that isn't really necessary to the concept):

    testqobject.h

    class TestQObject : public QObject
    {
    	Q_OBJECT
    	Q_PROPERTY(QString foo MEMBER foo)
    public:
    	explicit TestQObject(QObject* parent = nullptr);
    	TestQObject(const QString& _foo);
    	TestQObject(const TestQObject& rhs);
    
    	TestQObject& operator=(const TestQObject& rhs);
    
    	Q_INVOKABLE static QVariantList get_foos();
    	Q_INVOKABLE static QVariantList get_bars();
    signals:
    public slots:
    
    private:
    	QString foo;
    };
    
    Q_DECLARE_METATYPE(TestQObject);
    
    // Constructors etc were here....
    
    QVariantList TestQObject::get_foos()
    {
    	QVariantList ret;
    	ret << QVariant::fromValue(TestQObject("foo")) << QVariant::fromValue(TestQObject("baz"));
    	return ret;
    }
    
    QVariantList TestQObject::get_bars()
    {
    	QVariantList ret;
    	ret << QVariant::fromValue(TestQGadget("bar")) << QVariant::fromValue(TestQGadget("baz"));
    	return ret;
    }
    

    testqgadget.h

    class TestQGadget : public QObject
    {
    	Q_GADGET
    	Q_PROPERTY(QString bar MEMBER bar)
    public:
    	TestQGadget(const QString& _bar = QString());
    	TestQGadget(const TestQGadget& rhs);
    	~TestQGadget();
    	TestQGadget& operator=(const TestQGadget& rhs);
    signals:
    public slots:
    
    private:
    	QString bar;
    };
    
    Q_DECLARE_METATYPE(TestQGadget);
    
    // Constructors etc. were here....
    

    main.cc

    QObject* make_testqobject(QQmlEngine* qml_engine, QJSEngine* js_engine)
    {
    	return new TestQObject();
    }
    
    int main(int argc, char* argv[])
    {
    	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    	QGuiApplication app(argc, argv);
    	qmlRegisterType<TestQObject>("com.example.test", 1, 0, "TestQObject");
    	qmlRegisterType<TestQGadget>("com.example.test", 1, 0, "TestQGadget");
    	qmlRegisterSingletonType<TestQObject>("com.example.test", 1, 0, "TestQObjectSingle", &make_testqobject);
    	// and so on
    }
    

    main.qml

    import QtQuick 2.9
    import QtQuick.Window 2.2
    
    import com.example.test 1.0
    
    Window {
    	visible: true
    	width: 640
    	height: 480
    	title: qsTr("Q_OBJECT/Q_GADGET")
    
    	Component.onCompleted: {
    		var foos = TestQObjectSingle.get_foos();
    		for(var i = 0; i < foos.length; ++i)
    		{
    			console.log(foos[i]);
    			console.log(foos[i].foo);
    		}
    		var bars = TestQObjectSingle.get_bars();
    		for(i = 0; i < bars.length; ++i)
    		{
    			console.log(bars[i]);
    			console.log(bars[i].bar);
    		}
    	}
    }
    

    output is

    qml: QVariant(TestQObject)
    qml: undefined
    qml: QVariant(TestQObject)
    qml: undefined
    qml: TestQGadget(bar)
    qml: bar
    qml: TestQGadget(baz)
    qml: baz
    

    Sorry if the static functions in TestQObject are confusing, in the real thing I'm trying to do I get the list of objects from a different class, I just wanted to try to get everything into a minimal example. So my main question is why doesn't the TestQObject (which uses Q_OBJECT) list work (i.e. why doesn't the "foo" property get accessed) and is it possible to make it work? The second question is, I tried using Q_GADGET like in TestQGadget (there's not a whole lot of helpful documentation I could find on Q_GADGET) and for some reason if I don't inherit from QObject it won't compile, even though the examples I saw Q_GADGET classes weren't ever inheriting from anything. So the second question is, what would be the proper way to use the Q_GADGET version? And finally, if both Q_OBJECT and Q_GADGET are possible, which way would be better?

    sierdzioS 1 Reply Last reply
    0
    • J jacraig

      First let me tell you what my overall goal is: to pass a list (vector, array or whatever) of custom C++ objects into QML. I've been able to do this successfully (as in it compiles, runs and gives the result I want), but it's possible I'm doing something that I shouldn't. Also it's not clear to me why my solution works and not another one. Here is some code (omitting includes and some other stuff that isn't really necessary to the concept):

      testqobject.h

      class TestQObject : public QObject
      {
      	Q_OBJECT
      	Q_PROPERTY(QString foo MEMBER foo)
      public:
      	explicit TestQObject(QObject* parent = nullptr);
      	TestQObject(const QString& _foo);
      	TestQObject(const TestQObject& rhs);
      
      	TestQObject& operator=(const TestQObject& rhs);
      
      	Q_INVOKABLE static QVariantList get_foos();
      	Q_INVOKABLE static QVariantList get_bars();
      signals:
      public slots:
      
      private:
      	QString foo;
      };
      
      Q_DECLARE_METATYPE(TestQObject);
      
      // Constructors etc were here....
      
      QVariantList TestQObject::get_foos()
      {
      	QVariantList ret;
      	ret << QVariant::fromValue(TestQObject("foo")) << QVariant::fromValue(TestQObject("baz"));
      	return ret;
      }
      
      QVariantList TestQObject::get_bars()
      {
      	QVariantList ret;
      	ret << QVariant::fromValue(TestQGadget("bar")) << QVariant::fromValue(TestQGadget("baz"));
      	return ret;
      }
      

      testqgadget.h

      class TestQGadget : public QObject
      {
      	Q_GADGET
      	Q_PROPERTY(QString bar MEMBER bar)
      public:
      	TestQGadget(const QString& _bar = QString());
      	TestQGadget(const TestQGadget& rhs);
      	~TestQGadget();
      	TestQGadget& operator=(const TestQGadget& rhs);
      signals:
      public slots:
      
      private:
      	QString bar;
      };
      
      Q_DECLARE_METATYPE(TestQGadget);
      
      // Constructors etc. were here....
      

      main.cc

      QObject* make_testqobject(QQmlEngine* qml_engine, QJSEngine* js_engine)
      {
      	return new TestQObject();
      }
      
      int main(int argc, char* argv[])
      {
      	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      	QGuiApplication app(argc, argv);
      	qmlRegisterType<TestQObject>("com.example.test", 1, 0, "TestQObject");
      	qmlRegisterType<TestQGadget>("com.example.test", 1, 0, "TestQGadget");
      	qmlRegisterSingletonType<TestQObject>("com.example.test", 1, 0, "TestQObjectSingle", &make_testqobject);
      	// and so on
      }
      

      main.qml

      import QtQuick 2.9
      import QtQuick.Window 2.2
      
      import com.example.test 1.0
      
      Window {
      	visible: true
      	width: 640
      	height: 480
      	title: qsTr("Q_OBJECT/Q_GADGET")
      
      	Component.onCompleted: {
      		var foos = TestQObjectSingle.get_foos();
      		for(var i = 0; i < foos.length; ++i)
      		{
      			console.log(foos[i]);
      			console.log(foos[i].foo);
      		}
      		var bars = TestQObjectSingle.get_bars();
      		for(i = 0; i < bars.length; ++i)
      		{
      			console.log(bars[i]);
      			console.log(bars[i].bar);
      		}
      	}
      }
      

      output is

      qml: QVariant(TestQObject)
      qml: undefined
      qml: QVariant(TestQObject)
      qml: undefined
      qml: TestQGadget(bar)
      qml: bar
      qml: TestQGadget(baz)
      qml: baz
      

      Sorry if the static functions in TestQObject are confusing, in the real thing I'm trying to do I get the list of objects from a different class, I just wanted to try to get everything into a minimal example. So my main question is why doesn't the TestQObject (which uses Q_OBJECT) list work (i.e. why doesn't the "foo" property get accessed) and is it possible to make it work? The second question is, I tried using Q_GADGET like in TestQGadget (there's not a whole lot of helpful documentation I could find on Q_GADGET) and for some reason if I don't inherit from QObject it won't compile, even though the examples I saw Q_GADGET classes weren't ever inheriting from anything. So the second question is, what would be the proper way to use the Q_GADGET version? And finally, if both Q_OBJECT and Q_GADGET are possible, which way would be better?

      sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      @jacraig said in passing a list of custom objects to QML:

      I tried using Q_GADGET like in TestQGadget (there's not a whole lot of helpful documentation I could find on Q_GADGET) and for some reason if I don't inherit from QObject it won't compile

      Remove signals and slots from your header. Q_GADGET does not support them - hence you were getting compilation errors.

      If you want to return a list of objects that QML will understand, use a QObjectList.

      (Z(:^

      J 1 Reply Last reply
      1
      • sierdzioS sierdzio

        @jacraig said in passing a list of custom objects to QML:

        I tried using Q_GADGET like in TestQGadget (there's not a whole lot of helpful documentation I could find on Q_GADGET) and for some reason if I don't inherit from QObject it won't compile

        Remove signals and slots from your header. Q_GADGET does not support them - hence you were getting compilation errors.

        If you want to return a list of objects that QML will understand, use a QObjectList.

        J Offline
        J Offline
        jacraig
        wrote on last edited by
        #3

        @sierdzio said in passing a list of custom objects to QML:

        Remove signals and slots from your header. Q_GADGET does not support them - hence you were getting compilation errors.

        This does not seem to help. Still get the same compile error (when QObject inheritance is removed):

        /usr/include/qt5/QtQml/qqmlprivate.h:101:9: error: ‘QQmlPrivate::QQmlElement<T>::~QQmlElement() [with T = TestQGadget]’ marked ‘override’, but does not override
                 ~QQmlElement() override {
                 ^
        

        So I see QObjectList is a typedef for QList<QObject*>. I assume these pointers should be created on the heap. Can a QML object be their parent? In my case, no object on the C++ side would currently make sense as the parent of these items.

        sierdzioS 1 Reply Last reply
        0
        • J jacraig

          @sierdzio said in passing a list of custom objects to QML:

          Remove signals and slots from your header. Q_GADGET does not support them - hence you were getting compilation errors.

          This does not seem to help. Still get the same compile error (when QObject inheritance is removed):

          /usr/include/qt5/QtQml/qqmlprivate.h:101:9: error: ‘QQmlPrivate::QQmlElement<T>::~QQmlElement() [with T = TestQGadget]’ marked ‘override’, but does not override
                   ~QQmlElement() override {
                   ^
          

          So I see QObjectList is a typedef for QList<QObject*>. I assume these pointers should be created on the heap. Can a QML object be their parent? In my case, no object on the C++ side would currently make sense as the parent of these items.

          sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          @jacraig said in passing a list of custom objects to QML:

          So I see QObjectList is a typedef for QList<QObject*>. I assume these pointers should be created on the heap. Can a QML object be their parent? In my case, no object on the C++ side would currently make sense as the parent of these items.

          Yes it can, although setting in from C++ side is a bit cumbersome (entirely possible, though: find any children of your QQmlEngine::context instance).

          It is also 100% possible and legal to keep QObjects without a parent. The only downside of that is you have to remember to delete them yourself.

          (Z(:^

          1 Reply Last reply
          2
          • J Offline
            J Offline
            jacraig
            wrote on last edited by
            #5

            Just to bring this up to date, returning a QList<QObject*> does work to send a list of objects to QML. Note however that the QObjectList typedef did not work--QML complained when a function with that return type was attempted to be invoked.

            Thanks!

            1 Reply Last reply
            1

            • Login

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