Unsolved 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 -
@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 useQVariantList
and/orQVariantMap
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? -
@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 toQList<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 functionHow to access to CKey's attributes from Cmenu in QML?
-
@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