How can I fill a "ListView QML Type" with a model from a "QList<QString>"'?
-
Hello to all,
I have a QList<QString> (in c++) and now I want to use it as a model for a "ListView QML Type".
How can I do that?I've used a lot of Google and haven't found a solution yet. I hope someone has an idea how to solve this.
I wish you a nice week.
Greetings,
Sven -
Hi @sm-a,
One solution could be to use a QStringListModel as a Q_PROPERTY of a QObject shared with QML as context property.
//declaration in QObject derived class Q_PROPERTY(QStringListModel* stringList READ stringList) QStringListModel *m_stringList; //Updating the list m_setStringList->setStringList(list);
-
Hi,
QVariantList can be used also.#include <QVariantList> class VarModel : public QObject { Q_OBJECT Q_PROPERTY(QVariantList arr READ getarr WRITE setarr NOTIFY arrChanged) public: explicit VarModel(QObject *parent = nullptr); const QVariantList & getarr() const { return m_arr; } void setarr(const QVariantList & v) { m_arr = v; emit arrChanged(); } signals: void arrChanged(); private : QVariantList m_arr; }; #endif // VARMODEL_H //VarModel.cpp #include "varmodel.h" VarModel::VarModel(QObject *parent) : QObject(parent) { m_arr << "test" << "123" ;} //in main.cpp VarModel vr; engine.rootContext()->setContextProperty("mdl",&vr); //qml ListView{ anchors.fill: parent model:mdl.arr delegate:Rectangle { height: 120 width: parent.width color: "grey" border.width: 1 border.color: "white" Text { id: name text: mdl.arr[index] } } }
-
Hi @Gojir4,
can you please describe in more detail what I have to do. I have insert the Q_PROPERTY and the "QStringListModel *m_stringList;" in my c++ header file.
The "m_setStringList->setStringList(list);" have I insert into the cpp file. But how must I call it in the qml file?
I have tried following in the qml file:
<mylistview_id>.model = <id_name_from_c++>.stringListBut I get an error as follows:
<classname> has no member named ?stringList?; did you mean ?m_stringList??
case 0: reinterpret_cast< QStringListModel*>(_v) = _t->stringList(); break;
^~~~~~~~~~
m_stringListWhat I make false?
Thank you for your help.Greetings,
Sven -
Hi @sm-a,
As suggested by @LeLev, you need to provide your model as a context property in QML. Here is a simple example using QStringListModel:
C++
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QStringListModel model; model.setStringList(QStringList() << "This" << "is" << "my" << "stringlist"); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("myModel", &model); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
QML
import QtQuick 2.9 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") ListView{ anchors.fill: parent model: myModel delegate: Text{ text: display } } }
-
Hello @Gojir4
Thank you for the explanation.
I have a method that returns a "QStringList". This return value must now be transferred to the model and displayed. The model must also be updated after each click on a button that call the method again and refreshes the returned value and therefore the ListView.
I can't do it with the presented method.
I hope you have an idea for that.Greetings,
Sven -
This is a simplified example. You will probably not instantiate your model in the main.cpp in your final application. Usually it is a member of a class, like MainWindow, or a dedicated class for anything you want to do.
Can we see how is actually returned the stringlist in your code ?
-
@sm-a Sorry I was not clear. I mean where do you call this function ?
Is your classgetJobsFromI
deriving from QObject ?If yes, you can simply add the QStringListModel as a Q_PROPERTY of your classgetJobsFromI
, and then share the instance of this class with QML by usingQQmlContext::setContextProperty
, as demonstrated by @LeLev. Then when you update the stringlist, you can update the model at the same time.If
getJobsFromI
does not derive from QObject, you can the the QStringListModel instance as context property, but then you need to setup an access of your model from the place in your code where you update the stringlist, to be able to update the model as well.How is structured your app ? Where is located the
getJobsFromI
object ? -
I have now a test class created with default data. How can I implement this to a ListView QML? Please help!
getjobsfromi.cpp
#include "getjobsfromi.h" getJobsFromI::getJobsFromI(QObject *parent) : QObject(parent) { } QStringList getJobsFromI::getJobsForTiteAndCity(QString jobTitle, QString jobCity) { // TEST WITH STATIC DATA QStringList jobsStringList; jobsStringList << "Job1" << "Job2" << "Job3"; return jobsStringList; }
getjobsfromi.h
#ifndef GETJOBSFROMI_H #define GETJOBSFROMI_H #include <QObject> class getJobsFromI : public QObject { Q_OBJECT public: explicit getJobsFromI(QObject *parent = nullptr); QStringList getJobsForTiteAndCity(QString jobTitle, QString jobCity); signals: public slots: }; #endif // GETJOBSFROMI_H
-
@sm-a Are you calling
getJobsForTiteAndCity()
from C++ or QML ?Is your goal to call method
getJobsForTiteAndCity()
from QML to fill the ListView, according to the job title and city ? In this case I think you don't needgetJobsForTiteAndCity()
but you could use two properties for title and city, and then updating your model when these properties change.Anyway, here is how you can modify
getJobFromI
to provide a model to QML :
main.cpp#include "getjobsfromi.h" #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include <QStringListModel> int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); // QStringListModel model; // model.setStringList(QStringList() << "This" << "is" << "my" << "stringlist"); getJobsFromI gjfi; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("myModel", gjfi.jobListModel()); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
getjobsfromi.h
#ifndef GETJOBSFROMI_H #define GETJOBSFROMI_H #include <QObject> #include <QStringListModel> class getJobsFromI : public QObject { Q_OBJECT //declaration in QObject derived class Q_PROPERTY(QStringListModel* jobsListModel READ jobListModel) QStringListModel m_jobsListModel; public: explicit getJobsFromI(QObject *parent = nullptr); QStringList getJobsForTiteAndCity(QString jobTitle, QString jobCity); QStringListModel* jobListModel(); signals: public slots: }; #endif // GETJOBSFROMI_H
getjobsfromi.cpp
#include "getjobsfromi.h" getJobsFromI::getJobsFromI(QObject *parent) : QObject(parent) {} QStringList getJobsFromI::getJobsForTiteAndCity(QString jobTitle, QString jobCity) { // TEST WITH STATIC DATA QStringList jobsStringList; jobsStringList << "Job1" << "Job2" << "Job3"; //Update the model m_jobsListModel.setStringList(jobsStringList); return jobsStringList; } QStringListModel *getJobsFromI::jobListModel() { return &m_jobsListModel; }
This is just an example but as I said, if you only want to access the list from QML,
getJobsForTiteAndCity()
is useless and I would recommend to use another approach. -
@sm-a Hi,
- First create Q_Property of type QStringList as follows
Q_PROPERTY(QStringList myModel READ getJobsForTiteAndCity NOTIFY modelChanged) //OR QStringList m_model; Q_PROPERTY(QStringList model MEMBER m_model NOTIFY modelChanged)
- emit the signal whenever you update the data
QStringList getJobsFromI::getJobsForTiteAndCity(QString jobTitle, QString jobCity) { // TEST WITH STATIC DATA QStringList jobsStringList; jobsStringList << "Job1" << "Job2" << "Job3"; return jobsStringList; emit modelChanged(); //emitting signal }
- call the model variable "myModel" in QML listview
import QtQuick 2.9 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") ListView{ anchors.fill: parent model: getJobsFromI.myModel //classname.myModel delegate: Text{ text: modelData } } }
Try this , i'm pretty sure it works for you