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++>.stringList

    But 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_stringList

    What 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



  • @sm-a,

    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 ?



  • Hello @Gojir4

    I do it very simple. I do this as follows:

    QStringList getJobsFromI::getJobsForCity(QString city)
    {
        [...]
        return jobsStringList;
    }
    


  • @sm-a Sorry I was not clear. I mean where do you call this function ?
    Is your class getJobsFromI deriving from QObject ?If yes, you can simply add the QStringListModel as a Q_PROPERTY of your class getJobsFromI, and then share the instance of this class with QML by using QQmlContext::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 By using the first answer provided by @Gojir4



  • @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 need getJobsForTiteAndCity() 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,

    1. 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)
    
    
    1. 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
    }
    
    1. 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



  • I took another approach and executed the method directly in QML and set the "model". Now it works.

    I just solved it like this:
    listview.model = <myclassandmethod>(<heremyparameters>)

    Many thanks to everyone who answered me.

    Greetings,
    Sven


Log in to reply