How to list lists from C ++ to Qml?

I want to expose a QStringlist from C ++ to Qml and get access to its elements and their methods from the side of QML.

Here is what I have done so far:

this .h file for a class called manager.

#include <QObject> #include <QStringList> #include <QList> class Manager : public QObject { Q_OBJECT Q_PROPERTY(QStringList imagesPaths READ imagesPaths) Q_PROPERTY(QStringList imagesPaths READ imagesPaths2) Q_PROPERTY(QList<QStringList> imagesPathsLists READ imagesPathsLists) public: explicit Manager(QObject *parent = 0); QStringList imagesPaths() const; QStringList imagesPaths2() const; QList<QStringList> imagesPathsLists()const; signals: public slots: private: QStringList m_imagesPaths; QStringList m_imagesPaths2; QList<QStringList> m_imagesPathsLists; }; 

This is my .CPP file for implementing class methods

 #include "manager.h" Manager::Manager(QObject *parent) : QObject(parent) { m_imagesPaths << "one" << "two" << "three" << "four"; m_imagesPaths2 << "one-2" << "two-2" << "three-2" << "four-2"; m_imagesPathsLists << m_imagesPaths << m_imagesPaths2; } QStringList Manager::imagesPaths() const { return m_imagesPaths; } QStringList Manager::imagesPaths2() const { return m_imagesPaths2; } QList<QStringList> Manager::imagesPathsLists() const { return m_imagesPathsLists; } 

And the main.cpp file that contains the registration for my class

 #include <QtGui/QGuiApplication> #include "qtquick2applicationviewer.h" #include <qqmlcontext.h> #include "manager.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; Manager *mng = new Manager(); QQmlContext *ctxt = viewer.rootContext(); ctxt->setContextProperty("Manager",mng); viewer.setMainQmlFile(QStringLiteral("qml/listOfLists/main.qml")); viewer.showExpanded(); return app.exec(); } 

Finally, a .Qml file that tries to retrieve data from lists

 import QtQuick 2.0 Rectangle { width: 360 height: 360 MouseArea { anchors.fill: parent onClicked: { for(var i = 0; i < Manager.imagesPathsLists.count(); i++){ for(var j = 0; j < Manager.imagesPathsLists[i].count(); j++){ console.log(Manager.imagesPathsLists[i].at(j)) } } } } } 

Whenever I click on the rectangle, I get the following error

 QMetaProperty::read: Unable to handle unregistered datatype 'QList<QStringList>' for property 'Manager::imagesPathsLists' file:///E:/DevWork/build-listOfLists-Desktop_Qt_5_2_1_MinGW_32bit-Debug/qml/listOfLists/main.qml:10: TypeError: Cannot call method 'count' of undefined 

I have been trying to solve this problem for two days now. I tried QQmlListProperty , but without success I don't know what I messed up.

+6
source share
3 answers

You can achieve what you are trying to do by simply placing the QList<QStringList> in the container class that comes from QObject. The following example will explain this.

listoflist.h

 #ifndef LISTOFLIST_H #define LISTOFLIST_H #include <QObject> #include <QStringList> class ListOfList : public QObject { Q_OBJECT public: explicit ListOfList(QObject *parent = 0); void setListOfList(const QList<QStringList>& listOfList); Q_INVOKABLE qint32 count() const; Q_INVOKABLE qint32 subCount(const int & index) const; Q_INVOKABLE QString at(const int &i,const int &j); signals: public slots: private: QList<QStringList> m_listOfList; }; #endif // LISTOFLIST_H 

listoflist.cpp

 #include "listoflist.h" ListOfList::ListOfList(QObject *parent) : QObject(parent) { } void ListOfList::setListOfList(const QList<QStringList> &listOfList) { m_listOfList = listOfList; } qint32 ListOfList::count() const { return m_listOfList.count(); } qint32 ListOfList::subCount(const int &index) const { int subCount = -1; if(index>=0 && index<m_listOfList.count()) { subCount = m_listOfList.at(index).count(); } return subCount; } QString ListOfList::at(const int &i, const int &j) { QString value; if(i>=0 && i<m_listOfList.count()) { if(j>=0 && j<m_listOfList.at(i).count()) { value = m_listOfList.at(i).at(j); } } return value; } 

manager.h

 #include <QObject> #include <QStringList> #include <QList> #include <listoflist.h> class Manager : public QObject { Q_OBJECT Q_PROPERTY(QStringList imagesPaths READ imagesPaths) Q_PROPERTY(QStringList imagesPaths READ imagesPaths2) Q_PROPERTY(QObject* imagesPathsLists READ imagesPathsLists) public: explicit Manager(QObject *parent = 0); QStringList imagesPaths() const; QStringList imagesPaths2() const; QObject* imagesPathsLists(); signals: public slots: private: QStringList m_imagesPaths; QStringList m_imagesPaths2; QList<QStringList> m_imagesPathsLists; ListOfList m_listOfList; }; 

manager.cpp

 #include "manager.h" Manager::Manager(QObject *parent) : QObject(parent) { m_imagesPaths << "one" << "two" << "three" << "four"; m_imagesPaths2 << "one-2" << "two-2" << "three-2" << "four-2"; m_imagesPathsLists << m_imagesPaths << m_imagesPaths2; m_listOfList.setListOfList(m_imagesPathsLists); } QStringList Manager::imagesPaths() const { return m_imagesPaths; } QStringList Manager::imagesPaths2() const { return m_imagesPaths2; } QObject *Manager::imagesPathsLists() { return &m_listOfList; } 

main.cpp

 #include <QtGui/QGuiApplication> #include "qtquick2applicationviewer.h" #include <qqmlcontext.h> #include "manager.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QtQuick2ApplicationViewer viewer; Manager *mng = new Manager(); QQmlContext *ctxt = viewer.rootContext(); ctxt->setContextProperty("Manager",mng); viewer.setMainQmlFile(QStringLiteral("qml/SO_ListOfLists/main.qml")); viewer.showExpanded(); return app.exec(); } 

main.qml

 import QtQuick 2.0 Rectangle { width: 360 height: 360 Text { text: qsTr("Hello World") anchors.centerIn: parent } MouseArea { anchors.fill: parent onClicked: { var count = Manager.imagesPathsLists.count(); for(var i=0;i<count;i++) { var subCount = Manager.imagesPathsLists.subCount(i); console.debug("StringList number ->" + (i+1)) for(var j=0;j<subCount;j++) { var string = Manager.imagesPathsLists.at(i,j) console.debug(string) } console.debug("---------------------"); } } } } 
+5
source

You can use QVariantList instead of the QList property for imagesPathsLists.

The QML mechanism provides automatic type conversion between QVariantList and JavaScript arrays, as well as between QVariantMap and JavaScript objects.

.h:

 #include <QObject> #include <QStringList> #include <QList> class Manager : public QObject { Q_OBJECT Q_PROPERTY(QVariantList imagesPathsLists READ imagesPathsLists) public: explicit Manager(QObject *parent = 0); QVariantList imagesPathsLists() const; signals: public slots: private: QVariantList m_imagesPathsLists; }; 

.cpp:

 #include "manager.h" Manager::Manager(QObject *parent) : QObject(parent) { QStringList inner1; inner1 << "one" << "two" << "three" << "four"; QStringList inner2; inner2 << "one-2" << "two-2" << "three-2" << "four-2"; m_imagesPathsLists << QVariant(inner1) << QVariant(inner2); } 

.qml:

 import QtQuick 2.0 Rectangle { width: 360 height: 360 MouseArea { anchors.fill: parent onClicked: { for(var i = 0; i < Manager.imagesPathsLists.length(); i++){ for(var j = 0; j < Manager.imagesPathsLists[i].length(); j++){ console.log(Manager.imagesPathsLists[i][j]) } } } } } 
+3
source

Unfortunately, QML does not translate list types except those listed in the documentation. So, while the QStringList working, the QList<QStringList> does not.

You can use the QVariantList and populate it with the options that carry the QStringList . That should work.

+2
source

All Articles