Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Call for Presentations - Qt World Summit

    Solved QStringList in QML?

    General and Desktop
    3
    15
    10042
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      MScottM last edited by

      Is is possible to access items of a QStringList from QML? I want to do something like this:

      Label {
          id: label1
          text: myCppClassQstringList.index0
      }
      Label {
          id: label2
          text: myCppClassQstringList.index1
      }
      

      I've read that QStringList can be handled by QML natively, but I can't find any examples of how to do it.

      Best regards,

      Scott

      raven-worx 1 Reply Last reply Reply Quote 0
      • raven-worx
        raven-worx Moderators @MScottM last edited by raven-worx

        @MScottM said in QStringList in QML?:

        myCppClassQstringList[0]
        

        like any other list in JS

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply Reply Quote 3
        • M
          MScottM last edited by MScottM

          I can't seem to get access to the QStringList. I've tried various methods of exposing the variable to QML but I can't seem to make it work. It seems like it should be REALLY simple!

          I've exposed the class to QML using engine.rootContext:

          moduleFinder modFinder;
          
              engine.rootContext()->setContextProperty("modFinder", &modFinder);
          
          

          and from QML I can call the function that loads the QStringList:

          signal setModule(var lblMsg)
          
          Button {
                  id: clickme
                  x: 170
                  y: 0
                  visible: true
                  height: 100
                  width: 300
                  text: "click me"
                  onClicked: setModule("Module1")
              }
              onSetModule: {modFinder.setModule(lblMsg)     
              }
          

          I know this part is working, my QStringList gets loaded with the appropriate list of strings.

          When I try to set the QML labels' text using the resulting QStringList - nothing works. I've tried exposing the variable with Q_PROPERTY, etc.

          If someone could lead me a little further down the path, I would appreciate it!

          Best regards.

          By the way - thank you for your reply @raven-worx

          J.Hilk 1 Reply Last reply Reply Quote 0
          • J.Hilk
            J.Hilk Moderators @MScottM last edited by

            hi @MScottM

            can you show us a bit more, how your c++ class looks like?

            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct

            Qt Needs YOUR vote: https://bugreports.qt.io/browse/QTQAINFRA-4121


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            1 Reply Last reply Reply Quote 1
            • M
              MScottM last edited by

              Yes - moduleFinder.h:

              #ifndef MODULEFINDER_H
              #define MODULEFINDER_H
              
              #include <QObject>
              #include <QStringListModel>
              
              class moduleFinder : public QObject
              {
                  Q_OBJECT
                  Q_PROPERTY(QStringList moduleIo MEMBER m_moduleIo NOTIFY moduleIoChanged)
              
              public:
                  explicit moduleFinder( QObject *parent = nullptr );
              
                  QString fileName = "list.txt";
                  QString module;
                  QStringList ioList;
                  QStringList moduleIo;    
              
                  Q_INVOKABLE void loadModules();
                  QStringList getIo(QString);
                  int index = 0;
                  int newIndex = 0;
              
              public slots:
                  Q_INVOKABLE void setModule( const QString m_module );
              
              signals:
                  void moduleIoChanged(const QStringList &newModuleIoList);
                  
              private:
                 
              };
              
              #endif // MODULEFINDER_H
              

              moduleFinder.cpp:

              #include "modulefinder.h"
              #include <QFile>
              #include <QDebug>
              
              moduleFinder::moduleFinder(QObject *parent) : QObject(parent)
              {}
              
              void moduleFinder::setModule(QString m_module) {
                  module = m_module;
                  getIo(module);
              }
              
              void moduleFinder::loadModules(){
                  QFile moduleFile(fileName);
              
                  if (!moduleFile.exists()) {
                      qWarning() << "file doesn't exist!";}
                  else if (!moduleFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
                      qWarning() << "Not open"; }
                  else {
                      QTextStream textStream(&moduleFile);
                      while (!textStream.atEnd())
                          ioList << textStream.readLine();
                      moduleFile.close();
                  }   
              }
              
              QStringList moduleFinder::getIo(QString myModule) {
                  //qDebug()<<myModule;
                  int lines = ioList.length();
                  QString moduleId = myModule;
                  for (int i=0;i<lines;i++) {
                      //qDebug()<< "IO List" <<ioList.at(i);
                      if (ioList.at(i).contains(moduleId)) { // if module is found in list
                          index = i; // get index of position in list
                      }
                  }
                  newIndex = index + 32;
                  for (int y=index+1; y<newIndex+1; ++y) { // and copy relevant lines into new list
                      moduleIo << ioList.at(y); //   <-this is the QStringList I want to access
                  }    
                  emit moduleIoChanged(m_moduleIo);
                  //qDebug()<< moduleIo;
              }
              

              loadModules() is run once from main.cpp when the program starts.

              J.Hilk 1 Reply Last reply Reply Quote 0
              • J.Hilk
                J.Hilk Moderators @MScottM last edited by

                @MScottM
                I'm surprised this actually compiles, as your class has no member m_moduleIo the member variable is called moduleIo

                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct

                Qt Needs YOUR vote: https://bugreports.qt.io/browse/QTQAINFRA-4121


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                1 Reply Last reply Reply Quote 1
                • M
                  MScottM last edited by

                  Oh, I put it under 'private':

                  private:
                      QStringList m_moduleIo;
                  

                  I had been trying a couple different things to get something to work - I copied and pasted the code above from between a change I had tried.

                  J.Hilk 1 Reply Last reply Reply Quote 0
                  • J.Hilk
                    J.Hilk Moderators @MScottM last edited by

                    @MScottM
                    I have some difficulties to follow your problem.

                    Does this simple example help you?

                    //main.cpp
                    #include <QApplication>
                    #include <QQmlApplicationEngine>
                    
                    #include "myclass.h"
                    #include "QQmlContext"
                    
                    int main(int argc, char *argv[])
                    {
                        QApplication app(argc, argv);
                    
                        QQmlApplicationEngine engine;
                    
                        myClass mClass;
                    
                        engine.rootContext()->setContextProperty("cppListModel", &mClass);
                    
                        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                        if (engine.rootObjects().isEmpty())
                            return -1;
                    
                        return app.exec();
                    }
                    
                    //main.qml
                    import QtQuick 2.9
                    import QtQuick.Window 2.2
                    import QtQuick.Controls 2.5
                    
                    Window {
                        visible: true
                        width: 640
                        height: 480
                        title: qsTr("Hello World")
                    
                        id:root
                    
                    
                        ListView{
                            id: listView
                            anchors.fill: parent
                    
                            model: cppListModel.myListModel
                            delegate:Text {
                                text: modelData
                                color: index % 2 ? "red" : "blue"
                            }
                        }
                    }
                    
                    
                    //myClass
                    #ifndef MYCLASS_H
                    #define MYCLASS_H
                    
                    #include <QObject>
                    
                    class myClass : public QObject
                    {
                        Q_OBJECT
                        Q_PROPERTY(QStringList myListModel READ myListModel WRITE setMyListModel NOTIFY myListModelChanged)
                    public:
                        explicit myClass(QObject *parent = nullptr) :QObject(parent)
                        {
                            setMyListModel({"Item1", "Item2", "Item3", "Item4"});
                        }
                    
                    
                        QStringList myListModel() const
                        {
                            return m_myListModel;
                        }
                    
                    signals:
                    
                        void myListModelChanged(QStringList myListModel);
                    
                    public slots:
                    
                    
                    void setMyListModel(QStringList myListModel)
                    {
                        if (m_myListModel == myListModel)
                            return;
                    
                        m_myListModel = myListModel;
                        emit myListModelChanged(m_myListModel);
                    }
                    
                    private:
                    
                    QStringList m_myListModel;
                    };
                    
                    #endif // MYCLASS_H
                    

                    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct

                    Qt Needs YOUR vote: https://bugreports.qt.io/browse/QTQAINFRA-4121


                    Q: What's that?
                    A: It's blue light.
                    Q: What does it do?
                    A: It turns blue.

                    1 Reply Last reply Reply Quote 0
                    • M
                      MScottM last edited by

                      Hi @J-Hilk,

                      Thank you for your example - I apologize for not being more clear in what I'm trying to do. I have a GUI that I want to display the inputs and outputs of the modules of a PLC, so that when a user clicks the module button, the main page updates with that modules' list of I/O.

                      An over-simplified example:

                      0_1563283804617_9963df82-e5c0-4373-a592-cb0c69e47631-image.png

                      I can't get a ListView to work because it displays the whole list at a time, so I am trying to access a QStringList by index and put each indexes text in a corresponding label.

                      I hope that better explains the problem I'm having!

                      Best regards.

                      J.Hilk 1 Reply Last reply Reply Quote 0
                      • M
                        MScottM last edited by

                        I've made some progress following a different track!

                        I was able to bring the QStringList into QML by using a function to create an array:

                        Button {
                                id: clickme
                                x: 170
                                y: 0
                                visible: true
                                height: 100
                                width: 300
                                text: "click me"
                                onClicked: {setModule( "Module1" ); readlistValues.readValues(modFinder.moduleIo);
                                }
                            }
                            onSetModule: { modFinder.setModule(lblMsg) }    
                        

                        I had to create a property for each index value:

                        property string label1Text: ""
                        

                        then assign them:

                        Item {
                                id: readlistValues
                                function readValues(anArray) {
                                    for (var i=0; i<32; i++)
                                        console.log("list: ", anArray[i])
                                        label1Text = anArray[0]
                                }
                            }
                        

                        Now 'anArray' contains my list!! And I can assign the text as I hoped.

                        Label {
                                id: myLabel
                                x: 270
                                y: 106
                                width: 100
                                height: 50
                                text: label1Text
                                horizontalAlignment: Text.AlignHCenter
                                verticalAlignment: Text.AlignVCenter
                            }
                        

                        I followed information on this page:
                        Data Type conversion Between QML and c++

                        I'm sure I need to test this more, but I'm getting closer!

                        1 Reply Last reply Reply Quote 0
                        • J.Hilk
                          J.Hilk Moderators @MScottM last edited by

                          @MScottM

                          like this ? (I only changed the main.qml from the previous example)

                          import QtQuick 2.9
                          import QtQuick.Window 2.2
                          import QtQuick.Controls 2.5
                          
                          Window {
                              visible: true
                              width: 640
                              height: 480
                              title: qsTr("Hello World")
                          
                              id:root
                          
                          
                              Button{
                                  id:list1
                                  anchors{
                                      left:parent.left
                                      top:parent.top
                                      right:parent.horizontalCenter
                                      margins: 2
                                      rightMargin: 1
                                  }
                                  height: width / 3
                          
                                  text: qsTr("Set Model1")
                          
                                  onClicked:cppListModel.myListModel = ["Left 1", "Left 2"]
                                  background: Rectangle{
                                      color: cppListModel.myListModel[0] === "Left 1" ? "red" : "grey"
                                  }
                              }
                          
                              Button{
                                  id:list2
                                  anchors{
                                      left:parent.horizontalCenter
                                      top:parent.top
                                      right:parent.right
                                      margins: 2
                                      leftMargin: 1
                                  }
                                  height: width / 3
                          
                                  text:  qsTr("Set Model2")
                          
                                  onClicked:cppListModel.myListModel = ["Right 1", "Right 2"]
                          
                                  background: Rectangle{
                                      color: cppListModel.myListModel[0] === "Right 1" ? "red" : "grey"
                                  }
                              }
                          
                              Text {
                                  id: entry1
                                  text: cppListModel.myListModel[0]
                          
                                  anchors{
                                      left: parent.left
                                      right: parent.right
                                      top: list1.bottom
                                      margins: 2
                                  }
                                  height: list1.height
                                  verticalAlignment: Text.AlignVCenter
                                  horizontalAlignment: Text.AlignHCenter
                              }
                              Text {
                                  id: entry2
                                  text: cppListModel.myListModel[1]
                          
                                  anchors{
                                      left: parent.left
                                      right: parent.right
                                      top: entry1.bottom
                                      margins: 2
                                  }
                                  height: list1.height
                          
                                  verticalAlignment: Text.AlignVCenter
                                  horizontalAlignment: Text.AlignHCenter
                              }
                          }
                          

                          0_1563339030826_9779f82f-26ed-4c4a-bab3-3a534d28e954-image.png

                          0_1563339041241_027063d4-1562-48a2-a9bb-5a0f12d19d4f-image.png

                          0_1563339052858_85112240-72a7-4654-951a-a6c867c711d8-image.png

                          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct

                          Qt Needs YOUR vote: https://bugreports.qt.io/browse/QTQAINFRA-4121


                          Q: What's that?
                          A: It's blue light.
                          Q: What does it do?
                          A: It turns blue.

                          1 Reply Last reply Reply Quote 0
                          • M
                            MScottM last edited by MScottM

                            Hi @J-Hilk,

                            That is the right behavior, but not the way I'm hoping to go about it. It looks like you are updating the list from the QML button?

                            In my 'real' application there will be something like 30 pieces of information to update on each button press, and like 20 possible modules (as I said - my example was over-simplified!). That is why I'm hoping to use a text file. Something like a config file that can be changed by a user as needed to update the I/O lists.

                            I think I can actually mark this one as solved, as I can now access the list from the QML side and set my labels' text. Now my issue is that even though the list updates on the c++ side, it doesn't change in QML after the first button press.

                            Shall I open a new question?

                            J.Hilk 1 Reply Last reply Reply Quote 0
                            • J.Hilk
                              J.Hilk Moderators @MScottM last edited by

                              @MScottM said in QStringList in QML?:

                              It looks like you are updating the list from the QML button

                              yes, but it doesn't matter what updates the list, as long as setMyListModelis called

                              I think I can actually mark this one as solved, as I can now access the list from the QML side and set my labels' text. Now my issue is that even though the list updates on the c++ side, it doesn't change in QML after the first button press.

                              hey, at least progress ;)

                              Shall I open a new question?

                              You can, but this could continue as well

                              Can you create a minimal compellable example? Should simplify things drastically 😉

                              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct

                              Qt Needs YOUR vote: https://bugreports.qt.io/browse/QTQAINFRA-4121


                              Q: What's that?
                              A: It's blue light.
                              Q: What does it do?
                              A: It turns blue.

                              1 Reply Last reply Reply Quote 1
                              • M
                                MScottM last edited by

                                I figured out what is happening! It's in this function:

                                QStringList moduleFinder::getIo(QString myModule) {
                                    //qDebug() << "my Module from QML" << myModule; 
                                    int lines = ioList.length();
                                    //qDebug() << "lines:" << lines;                
                                    QString moduleId = myModule;
                                    for (int i=0;i<lines;i++) {
                                        //qDebug() << "IO List" << ioList.at(i);
                                        if (ioList.at(i).contains(moduleId)) {      
                                            index = i;                             
                                        }
                                    }
                                    newIndex = index + 32;
                                    qDebug()<<"Index:" << index;                   
                                    qDebug()<<"New Index:" << newIndex;             
                                    for (int y=index+1; y<newIndex+1; ++y) {
                                  // PROBLEM IS HERE
                                  //m_moduleIo is being appended with a new list each time
                                        m_moduleIo << ioList.at(y);
                                  // I need to check and clear it at each access, but not sure how!?
                                        qDebug() << "io List" << ioList.at(y);      
                                    }
                                    emit moduleIoChanged(m_moduleIo);              
                                    qDebug()<< "m_moduleIO" << m_moduleIo;          
                                    return m_moduleIo;
                                    //emit moduleIoChanged(m_moduleIo);
                                }
                                
                                
                                1 Reply Last reply Reply Quote 0
                                • M
                                  MScottM last edited by

                                  Update:

                                  <smacks own forehead>

                                  QStringList moduleFinder::getIo(QString myModule) {   
                                      int lines = ioList.length();            
                                      QString moduleId = myModule;
                                      for (int i=0;i<lines;i++) {        
                                          if (ioList.at(i).contains(moduleId)) {      
                                              index = i;                             
                                          }
                                      }
                                      newIndex = index + 32;    
                                      m_moduleIo.clear();  //<- RESET BEFORE EACH TIME THROUGH      
                                      for (int y=index+1; y<newIndex+1; ++y) {  
                                          m_moduleIo << ioList.at(y);  
                                          qDebug() << "io List" << ioList.at(y);      
                                      }
                                      emit moduleIoChanged(m_moduleIo);          
                                      return m_moduleIo;    
                                  }
                                  

                                  It all works as I hoped now.

                                  1 Reply Last reply Reply Quote 0
                                  • First post
                                    Last post