Access to nested c++ objects in QML?



  • Hey,
    Imagine you have a page that it contains one or more menus and each menus has one or more keys inside and each keys has its features, how to export it into QML in a way all of nested objects inside higher level class be accessible?

    I've tried inheritance from QObject and using QVector to store variable number of nested objects but I faced to a lots of problems.

    For instance I want to access to keys feature with something like below snippet code:

    Rectangle
    {
    width:100
    height:100
    color:"red"
    Text{
    anchors{centerIn:parent}
    text:CPM.CPage[0].CMenus[0].CKeys[0].Name
    }
    }
    

    Yours,
    Ali


  • Moderators

    @Alien said in Access to nested c++ objects in QML?:

    I've tried inheritance from QObject and using QVector to store variable number of nested objects but I faced to a lots of problems.

    What were your problems?
    Also you should use QVariantList and/or QVariantMap instead. See here.



  • Dear @raven-worx ,

    In fact the problem is something ridiculous, I don't expect that something like this become a problem to me!
    By the way could you please have a look at the below code :

    Key Header:

    #ifndef CKEY_H
    #define CKEY_H
    
    #include <QObject>
    #include <QColor>
    #include <QString>
    
    class CKey:public QObject
    {
    Q_OBJECT
        Q_PROPERTY(QString Name READ name WRITE setName NOTIFY nameChanged)
        Q_PROPERTY(int Number READ number WRITE setNumber NOTIFY numberChanged)
        Q_PROPERTY(QColor Color READ color WRITE setColor NOTIFY colorChanged)
    private:
        QString m_name;
        int m_number;
        QColor m_color;
    public:
        CKey(QObject *parent=nullptr);
    
        QString name() const;
        void setName(const QString &name);
        int number() const;
        void setNumber(int number);
        QColor color() const;
        void setColor(const QColor &color);
    
        ~CKey();
    signals:
        void nameChanged();
        void numberChanged();
        void colorChanged();
    };
    
    #endif // CKEY_H
    
    

    Key source file :

    #include "ckey.h"
    
    
    /*=========================SETTER/GETTER================================*/
    QString CKey::name() const
    {
        return m_name;
    }
    
    void CKey::setName(const QString &name)
    {
        m_name = name;
        emit nameChanged();
    }
    
    int CKey::number() const
    {
        return m_number;
    }
    
    void CKey::setNumber(int number)
    {
        m_number = number;
        emit numberChanged();
    }
    
    QColor CKey::color() const
    {
        return m_color;
    }
    
    void CKey::setColor(const QColor &color)
    {
        m_color = color;
        emit colorChanged();
    }
    
    
    /*=====================================================================*/
    CKey::CKey(QObject *parent):QObject(parent)
    {
        m_color = Qt::red;
        m_number = 0;
        m_name="default";
    
    }
    /*=====================================================================*/
    
    /*=====================================================================*/
    CKey::~CKey()
    {
    
    }
    /*=====================================================================*/
    
    

    Menu Header:

    #ifndef CMENU_H
    #define CMENU_H
    
    #include <QObject>
    #include <QString>
    #include <QVector>
    #include "ckey.h"
    
    class CMenu : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString Name READ name WRITE setName NOTIFY nameChanged)
        Q_PROPERTY(QVector<CKey> KeysList READ keysList WRITE setKeysList NOTIFY keysListChanged)
    private :
        QString m_name;
        QVector<CKey> m_keysList;
    
    public:
        explicit CMenu(QObject *parent = nullptr);
        ~CMenu();
    
        QString name() const;
        void setName(const QString &name);
    
        QVector<CKey> keysList() const;
        void setKeysList(const QVector<CKey> &keysList);
    
    signals:
        void nameChanged();
        void keysListChanged();
    
    public slots:
    };
    
    #endif // CMENU_H
    
    

    Menu source file:

    #include "cmenu.h"
    
    QString CMenu::name() const
    {
        return m_name;
    }
    
    void CMenu::setName(const QString &name)
    {
        m_name = name;
    }
    
    QVector<CKey> CMenu::keysList() const
    {
        return m_keysList;
    }
    
    void CMenu::setKeysList(const QVector<CKey> &keysList)
    {
        m_keysList = keysList;
    }
    
    CMenu::CMenu(QObject *parent) : QObject(parent)
    {
    
    }
    
    CMenu::~CMenu()
    {
        if(m_keysList.length()>0)
            m_keysList.clear();
    
    }
    
    

    And finally main:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "ckey.h"
    #include "cmenu.h"
    
    int main(int argc, char *argv[])
    {
    
        CKey key[5];
    
        key[0].setName("One");
        key[1].setName("TWO");
        key[2].setName("THREE");
        key[3].setName("FOUR");
        key[4].setName("FIVE");
    
        CMenu menu;
    
        for (int index = 0; index < 5; ++index)
        {
                menu.keysList().append(key[index]);
        }
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
    
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
        QQmlContext * context=engine.rootContext();
        context->setContextProperty("CMenu",&menu);
        return app.exec();
    }
    
    

    Compile Errors:
    error: use of deleted function 'CKey& CKey::operator=(const CKey&)'
    use of deleted function 'CKey::CKey(const CKey&)'
    Of course these errors say to me that CKey need to implement operator = and CKey(const CKey&) but why?Does it have any better way to doing that?


  • Moderators

    @Alien said in Access to nested c++ objects in QML?:

    QVector<CKey>

    The errors are because you use a QObject derived class a reference/copy type. This is not allowed. QObject must be allocated on the heap (=pointers).
    So change your declaration and properties to QList<CKey*>



  • Dear @raven-worx,
    I changed the CMenu class to below:

    Header

    #ifndef CMENU_H
    #define CMENU_H
    
    #include <QObject>
    #include <QString>
    #include <QVector>
    #include "ckey.h"
    
    class CMenu : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString Name READ name WRITE setName NOTIFY nameChanged)
        Q_PROPERTY(QList<CKey*> KeysList READ keysList NOTIFY keysListChanged)
    private :
        QString m_name;
        QList<CKey*> m_keysList;
    
    public:
        explicit CMenu(QObject *parent = nullptr);
        ~CMenu();
    
        QString name() const;
        void setName(const QString &name);
        void addKey(CKey* key);
    
        QList<CKey*> keysList() const;
    
    signals:
        void nameChanged();
        void keysListChanged();
    
    public slots:
    };
    
    #endif // CMENU_H
    
    
    

    source

    #include "cmenu.h"
    
    QString CMenu::name() const
    {
        return m_name;
    }
    
    void CMenu::setName(const QString &name)
    {
        m_name = name;
    }
    
    void CMenu::addKey(CKey *key)
    {
        m_keysList.append(key);
    }
    
    QList<CKey *> CMenu::keysList() const
    {
        return m_keysList;
    }
    
    
    
    CMenu::CMenu(QObject *parent) : QObject(parent)
    {
    
    }
    
    CMenu::~CMenu()
    {
        if(m_keysList.length()>0)
            m_keysList.clear();
    
    }
    
    

    and main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "ckey.h"
    #include "cmenu.h"
    
    int main(int argc, char *argv[])
    {
    
        CKey *key = new CKey[5];
    
        key[0].setName("One");
        key[1].setName("TWO");
        key[2].setName("THREE");
        key[3].setName("FOUR");
        key[4].setName("FIVE");
    
        CMenu menu;
        menu.setName("Test");
    
        for (int index = 0; index < 5; ++index)
        {
            menu.addKey(&key[index]);
        }
    
    
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
    
        QGuiApplication app(argc, argv);
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
        QQmlContext * context=engine.rootContext();
        context->setContextProperty("CMenu",&menu);
        return app.exec();
    }
    
    

    it build correctly now how to access to keys from qml:

    import QtQuick 2.10
    import QtQuick.Window 2.10
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
    
        Rectangle
        {
            width:150
            height: 150
            color: "yellow"
            Text {
                id: txtID
                text: qsTr(CMenu.KeysList.at(0).Name)
            }
        }
    }
    
    

    Errors:

    qrc:/main.qml:18: ReferenceError: CMenu is not defined
    qrc:/main.qml:18: TypeError: Property 'at' of object QVariant(QVector<CKey*>) is not a function

    How to access to CKey's attributes from Cmenu in QML?


  • Moderators

    @Alien said in Access to nested c++ objects in QML?:

    How to access to CKey's attributes from Cmenu in QML?

    When you just want to read values:

    CMenu {
        id: cm
    }
    ...
    cm.KeysList[0].Name
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.