Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Issues with QVariantLists/QLists of custom QObjects
Qt 6.11 is out! See what's new in the release blog

Issues with QVariantLists/QLists of custom QObjects

Scheduled Pinned Locked Moved General and Desktop
6 Posts 2 Posters 2.5k Views 1 Watching
  • 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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    I'm hoping to get some help with a snag I've run into on a personal project. Essentially I have a custom QObject inheritor that contains its own various elements of data, and another custom QObject that I would like to have some collection element of multiple instances of the other custom QObject. I've tried various ways of implementing this and thus far I've had no real success, the closest being with a QVariantList. The following snippets are from an example I wrote to recreate the issue, but they follow the same general structure as their more detailed counterparts.

    Data represents the initial custom QObject.

    "data.h"

    @#ifndef DATA_H
    #define DATA_H
    #include <QObject>

    class Data : public QObject
    {

    Q_OBJECT
    public:
    explicit Data(QObject *parent = 0);
    Data(const Data &other);
    ~Data();
    QString getName();
    QString getContent();
    void setName(QString newName);
    void setContent(QString newContent);

    private:
    QString name, content;
    };

    Q_DECLARE_METATYPE(Data)

    #endif // DATA_H@

    "data.cpp"

    @#include "data.h"

    Data::Data(QObject *parent) :
    QObject(parent)
    {
    name = "testData";
    content = "testContent";
    }

    Data::Data(const Data &other){}

    Data::~Data(){}

    QString Data::getName(){return name;}

    QString Data::getContent(){return content;}

    void Data::setName(QString newName){name = newName;}

    void Data::setContent(QString newContent){content = newContent;}@

    TestContainer is the object which will hold some collection of Data

    "testcontainer.h"

    @#ifndef TESTCONTAINTER_H
    #define TESTCONTAINER_H

    #include <QObject>
    #include <QString>
    #include <QVariantList>
    #include "data.h"

    class TestContainer : public QObject
    {
    Q_OBJECT
    public:
    explicit TestContainer(QObject *parent = 0);
    TestContainer(const TestContainer &other);
    Q_INVOKABLE QVariantList getList();

    private:
    QString name;
    QVariantList theList;

    };

    Q_DECLARE_METATYPE(TestContainer)

    #endif // TESTCONTAINTER_H@

    "testcontainer.cpp"

    @#include "testcontainer.h"

    TestContainer::TestContainer(QObject *parent) :
    QObject(parent)
    {
    name = "test container";
    Data temp;
    theList.append(QVariant::fromValue(temp));
    }

    TestContainer::TestContainer(const TestContainer &other){
    name = other.name;
    theList = other.theList;
    }

    QVariantList TestContainer::getList(){return theList;}@

    "main.cpp"

    @#include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>

    #include "testcontainer.h"

    int main(int argc, char *argv[])
    {
    QApplication app(argc, argv);

    qRegisterMetaType<Data>("Data");
    qRegisterMetaType<TestContainer>("TestContainer");
    //qmlRegisterType<Data>("custom.data", 1, 0, "Data");
    //qmlRegisterType<TestContainer>("custom.testcontainer", 1, 0, "TestContainer");

    QQmlApplicationEngine engine;

    TestContainer theContainer;
    engine.rootContext()->setContextProperty("theContainer", &theContainer);

    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
    }@

    "main.qml"

    @import QtQuick 2.3
    import QtQuick.Controls 1.2
    //import custom.data 1.0
    //import custom.testcontainer 1.0

    ApplicationWindow {
    visible: true
    width: 320
    height: 240
    title: qsTr("Testing Functionality")

    Text {
    text: theContainer.getList()[0].getName();
    anchors.centerIn: parent
    }
    }@

    Put together all of this provides me with a nice:

    "TypeError: Property 'getName' of object QVariant(Data) is not a function"

    Thoughts?

    1 Reply Last reply
    0
    • A Offline
      A Offline
      andre
      wrote on last edited by
      #2

      This setup is not going to work. QObject derived classes are not copyable. In order to insert them into a container, they need to be copyable. QObject are shared as pointers, not as values.

      1 Reply Last reply
      0
      • ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #3

        So you're telling me there is no way to expose any sort of container of QObject inheritors to QML?

        What's the best course of action here then? To my understanding in order to expose any properties of an object to QML it has to be a QObject. Is this not the case? How do I take a collection of custom objects and expose them?

        1 Reply Last reply
        0
        • A Offline
          A Offline
          andre
          wrote on last edited by
          #4

          You can expose pointers to objects, but not the objects themselves. This is basic Qt. QObjects cannot be copied, period. Note that QML handles pointers to objects just fine. All objects in QML really are pointers in the background.

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            What is your suggestion then? How does one expose a container of QObject-derived items or rather a container of pointers to QObject-derived items? I've attempted to use QList<QObject*> but have been met with similar issues.

            1 Reply Last reply
            0
            • ? Offline
              ? Offline
              A Former User
              wrote on last edited by
              #6

              After hours of research and more trial and error I've finally discovered a solution that works for me. Rather than trying to force a QList<Object*> or QVariantList to function correctly I managed to get everything working with QList<Data*> and QQmlListProperty<Data>. Currently I am able to both use the QList as a model for things like TableView and am also able to access individual elements of the list. For models it goes something like:

              @model: testContainer.theList@

              And to access an individual element something like:

              @text: theContainer.getData(0).name@

              The following is the current code that achieves this:

              "data.h"

              @#ifndef DATA_H
              #define DATA_H

              #include <QObject>

              class Data : public QObject
              {
              Q_OBJECT
              Q_PROPERTY(QString name READ getName WRITE setName)
              Q_PROPERTY(QString content READ getContent WRITE setContent)
              public:
              explicit Data(QObject *parent = 0);
              QString getName();
              QString getContent();
              void setName(QString newName);
              void setContent(QString newContent);

              private:
              QString name, content;
              };

              #endif // DATA_H@

              "data.cpp"

              @#include "data.h"

              Data::Data(QObject *parent) :
              QObject(parent){}

              QString Data::getName(){return name;}

              QString Data::getContent(){return content;}

              void Data::setName(QString newName){name = newName;}

              void Data::setContent(QString newContent){content = newContent;}@

              "testContainer.h"

              @#ifndef TESTCONTAINTER_H
              #define TESTCONTAINER_H

              #include <QObject>
              #include <QList>
              #include <QQmlListProperty>

              #include "data.h"

              class TestContainer : public QObject
              {
              Q_OBJECT
              Q_PROPERTY(QQmlListProperty<Data> theList READ getList)
              public:
              explicit TestContainer(QObject parent = 0);
              QQmlListProperty<Data> getList();
              void addData(Data
              d);
              Q_INVOKABLE Data* getData(int i);

              private:
              QString name;
              QList<Data*> theList;
              };

              #endif // TESTCONTAINTER_H@

              "testContainer.cpp"

              @#include "testcontainer.h"

              TestContainer::TestContainer(QObject *parent) :
              QObject(parent){}

              QQmlListProperty<Data> TestContainer::getList(){
              return QQmlListProperty<Data>(this, theList);}

              void TestContainer::addData(Data* d){theList.append(d);}

              Data* TestContainer::getData(int i){return theList.at(i);}@

              "main.cpp"

              @#include <QApplication>
              #include <QQmlApplicationEngine>
              #include <QQmlContext>
              #include <QTQml>

              #include "testcontainer.h"

              int main(int argc, char *argv[])
              {
              QApplication app(argc, argv);

              qmlRegisterType<Data>("Custom", 1, 0, "Data");
              qmlRegisterType<TestContainer>("Custom", 1, 0, "TestContainer");
              
              QQmlApplicationEngine engine;
              
              TestContainer theContainer;
              Data d1;
              d1.setName("test name 1");
              d1.setContent("test content 1");
              Data d2;
              d2.setName("test name 2");
              d2.setContent("test content 2");
              theContainer.addData(&d1);
              theContainer.addData(&d2);
              engine.rootContext()->setContextProperty("theContainer", &theContainer);
              
              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
              
              return app.exec();
              

              }@

              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