Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Using same qml for multiple instantiation

Using same qml for multiple instantiation

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
qml
14 Posts 3 Posters 4.6k Views 3 Watching
  • 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 Offline
    M Offline
    milan
    wrote on last edited by
    #1

    Hello, I am wondering is it possible to use same qml file so that the qml component can be instantianted multiple times in the UI. But each instance of qml component will get different data from C++? Is it possible? Please help

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      Yes. This is exactly what happens when you're using a C++ model (QAbstractItemModel) with views: Repeater, ListView, GridView etc.

      You can also use same component with different data in Loader, SwipeView, TabView etc.

      (Z(:^

      M 1 Reply Last reply
      3
      • ODБOïO Offline
        ODБOïO Offline
        ODБOï
        wrote on last edited by
        #3

        Hi @milan
        Yes this is possible,
        if your .qml file/component defined like this :

        //Mycomponent.qml
        
        Item{
        property string m_name 
        }
        

        you can do :

        Mycomponent{
        id:c1
        m_name : cppObj.name1  // assuming you have an object called cppObj reachable in QML with Q_Property *name1*
        }
        Mycomponent{
        id:c2
        m_name : cppObj.name2
        }
        
        M 1 Reply Last reply
        2
        • sierdzioS sierdzio

          Yes. This is exactly what happens when you're using a C++ model (QAbstractItemModel) with views: Repeater, ListView, GridView etc.

          You can also use same component with different data in Loader, SwipeView, TabView etc.

          M Offline
          M Offline
          milan
          wrote on last edited by
          #4

          Hello @sierdzio. Thank you for reply. So, there is single C++ model (QAbstractItemModel) feeding items in GridView, ListView, Repeater? What datastructure should I choose (suppose if I chose GridView as view). Is QVariantList good idea for the GridView.Could you give me a example or link so I could check. Thank you.

          sierdzioS 1 Reply Last reply
          0
          • M milan

            Hello @sierdzio. Thank you for reply. So, there is single C++ model (QAbstractItemModel) feeding items in GridView, ListView, Repeater? What datastructure should I choose (suppose if I chose GridView as view). Is QVariantList good idea for the GridView.Could you give me a example or link so I could check. Thank you.

            sierdzioS Offline
            sierdzioS Offline
            sierdzio
            Moderators
            wrote on last edited by
            #5

            @milan said in Using same qml for multiple instantiation:

            Hello @sierdzio. Thank you for reply. So, there is single C++ model (QAbstractItemModel) feeding items in GridView, ListView, Repeater? What datastructure should I choose (suppose if I chose GridView as view). Is QVariantList good idea for the GridView.Could you give me a example or link so I could check. Thank you.

            Answer depends entirely on what you are trying to achieve. An introduction to this topic can be found here.

            Info about using C++ data models can be found here.

            (Z(:^

            1 Reply Last reply
            0
            • ODБOïO ODБOï

              Hi @milan
              Yes this is possible,
              if your .qml file/component defined like this :

              //Mycomponent.qml
              
              Item{
              property string m_name 
              }
              

              you can do :

              Mycomponent{
              id:c1
              m_name : cppObj.name1  // assuming you have an object called cppObj reachable in QML with Q_Property *name1*
              }
              Mycomponent{
              id:c2
              m_name : cppObj.name2
              }
              
              M Offline
              M Offline
              milan
              wrote on last edited by
              #6

              @LeLev. Thank you for your reply. You are using Q_PROPERTY. Is it possible using QAbstractItemModel? If I use Q_PROPERTY, I need to use a lot of Q_PROPERTY. Because I have around 50 variables which needs to be displayed in the UI. But not all 50 variables has to be displayed, only the variables chosen by the user while the application is running. So, which variables is chosen is not known until the application is run and user chooses the variables

              ODБOïO 1 Reply Last reply
              0
              • M milan

                @LeLev. Thank you for your reply. You are using Q_PROPERTY. Is it possible using QAbstractItemModel? If I use Q_PROPERTY, I need to use a lot of Q_PROPERTY. Because I have around 50 variables which needs to be displayed in the UI. But not all 50 variables has to be displayed, only the variables chosen by the user while the application is running. So, which variables is chosen is not known until the application is run and user chooses the variables

                ODБOïO Offline
                ODБOïO Offline
                ODБOï
                wrote on last edited by
                #7

                hi @milan yes of course you can use QAbstractItemModel if you want

                M 1 Reply Last reply
                0
                • ODБOïO ODБOï

                  hi @milan yes of course you can use QAbstractItemModel if you want

                  M Offline
                  M Offline
                  milan
                  wrote on last edited by
                  #8

                  @LeLev @sierdzio. Thanks to both of you. I created following:

                  #include <QGuiApplication>
                  #include <QQmlApplicationEngine>
                  #include <QQmlContext>
                  
                  #include <model.h>
                  
                  int main(int argc, char *argv[])
                  {
                      QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
                  
                      QGuiApplication app(argc, argv);
                  
                      QQmlApplicationEngine* engine = new QQmlApplicationEngine();
                      Model firstmodel("FirstModel");
                      Model secondmodel("SecondModel");
                  
                      engine->rootContext()->setContextProperty("FirstModel", &firstmodel);
                      engine->rootContext()->setContextProperty("SecondModel", &secondmodel);
                  
                      engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
                      if (engine->rootObjects().isEmpty())
                          return -1;
                      return app.exec();
                  }
                  
                  #ifndef MODEL_H
                  #define MODEL_H
                  
                  #include <QObject>
                  #include <QTimer>
                  #include <QDebug>
                  
                  class Model : public QObject
                  {
                      Q_OBJECT
                      Q_PROPERTY(int num READ num WRITE setNum NOTIFY numChanged)
                  
                  public:
                      explicit Model(QString name, QObject *parent = nullptr);
                      ~Model();
                  
                      int num() const;
                  signals:
                      void numChanged(int num);
                      void operate();
                  
                  public slots:
                      void setNum(int num);
                      void update();
                  
                  private:
                      QString m_name;
                      int m_num;
                      QTimer* m_timer;
                  };
                  
                  #endif // MODEL_H
                  
                  #include "model.h"
                  
                  Model::Model(QString name, QObject *parent) : QObject (parent)
                  {
                      m_num = 10;
                      m_name = name;
                      qDebug() << "Creating Model:" << m_name;
                      m_timer = new QTimer(this);
                      connect(m_timer, SIGNAL(timeout()), this, SLOT(update()));
                      m_timer->start(1000);
                  }
                  
                  Model::~Model()
                  {
                      qDebug() << "Destructing Model:" << m_name;
                  }
                  
                  int Model::num() const
                  {
                      return m_num;
                  }
                  
                  void Model::update()
                  {
                      m_num += 5;
                      this->setNum(m_num);
                      qDebug() << "Updating" << m_name << m_num;
                      emit numChanged(m_num);
                  
                      if (m_num == 100) {
                          m_timer->stop();
                          qDebug() << "Timer is stopped";
                      }
                  }
                  
                  void Model::setNum(int num)
                  {
                      if (m_num == num)
                          return;
                      qDebug() << "Setting value:" << num;
                      m_num = num;
                      emit numChanged(m_num);
                  }
                  
                  import QtQuick 2.9
                  import QtQuick.Controls 2.4
                  import QtQuick.Layouts 1.11
                  import QtQuick.Controls.Styles 1.4
                  import QtQuick.Extras 1.4
                  
                  ApplicationWindow {
                      visible: true
                      width: 640
                      height: 480
                      title: qsTr("App")
                  
                      Gauge {
                          x: 10
                          y: 10
                          minimumValue: 0
                          value: FirstModel.num
                          maximumValue: 100
                      }
                      Gauge {
                          x: 100
                          y: 10
                          minimumValue: 0
                          value: SecondModel.num
                          maximumValue: 100
                      }
                  }
                  

                  From the above code, I can use most of Gauge element (qml) again, but you can also see that it is hard coded at value. What I would like to do is "creating a C++ model object dynamically when it needs to be constructed and this should trigger to add corresponding Gauge element(qml) in QML window application."

                  1 Reply Last reply
                  0
                  • sierdzioS Offline
                    sierdzioS Offline
                    sierdzio
                    Moderators
                    wrote on last edited by
                    #9

                    @milan said in Using same qml for multiple instantiation:

                    What I would like to do is "creating a C++ model object dynamically when it needs to be constructed and this should trigger to add corresponding Gauge element(qml) in QML window application."

                    Either add some signals/slots to invoke Qt.createComponent() in QML in response to C++ object being created. Or use a grid & model as mentioned earlier (then if Gauge is the delegate it will be created automatically when you add new element to the model). Or inject your C++ object into QML engine (by adding it to children of your root element for example) - but that is hacky and hard to do.

                    (Z(:^

                    M 1 Reply Last reply
                    1
                    • sierdzioS sierdzio

                      @milan said in Using same qml for multiple instantiation:

                      What I would like to do is "creating a C++ model object dynamically when it needs to be constructed and this should trigger to add corresponding Gauge element(qml) in QML window application."

                      Either add some signals/slots to invoke Qt.createComponent() in QML in response to C++ object being created. Or use a grid & model as mentioned earlier (then if Gauge is the delegate it will be created automatically when you add new element to the model). Or inject your C++ object into QML engine (by adding it to children of your root element for example) - but that is hacky and hard to do.

                      M Offline
                      M Offline
                      milan
                      wrote on last edited by
                      #10

                      @sierdzio . Thanks, yes adding delegate works with single element. So, I added QList<int> to Q_PROPERTY. How can I access each element in QML?

                          GridView {
                              width: 300; height: 200
                              model:  FirstModel
                              delegate: Gauge {
                                  x: 10
                                  y: 10
                                  minimumValue: 0
                                  value: num[0] // how to add more elements
                                  maximumValue: 100
                              }
                          }
                      
                          Q_PROPERTY(QList<int> num READ num WRITE setNum NOTIFY numChanged)
                      
                      1 Reply Last reply
                      0
                      • sierdzioS Offline
                        sierdzioS Offline
                        sierdzio
                        Moderators
                        wrote on last edited by
                        #11

                        What is FirstModel?

                        (Z(:^

                        M 1 Reply Last reply
                        0
                        • sierdzioS sierdzio

                          What is FirstModel?

                          M Offline
                          M Offline
                          milan
                          wrote on last edited by
                          #12

                          Hello @sierdzio,

                             QQmlApplicationEngine* engine = new QQmlApplicationEngine();
                             Model firstmodel("FirstModel", 3);
                             engine->rootContext()->setContextProperty("FirstModel", &firstmodel);
                             engine->load(QUrl(QStringLiteral("qrc:/main.qml")));
                          

                          FirstModel is just name of object with 3 QList int items in Model Class.

                          1 Reply Last reply
                          0
                          • sierdzioS Offline
                            sierdzioS Offline
                            sierdzio
                            Moderators
                            wrote on last edited by
                            #13

                            Ok, so that is a bit wrong.

                            Either change your Model into a proper model (QAbstractItemModel or QListItemModel etc.). Or (easier) set the num property as model, like this:

                            GridView {
                                    width: 300; height: 200
                                    model:  FirstModel.num
                                    delegate: Gauge {
                                        x: 10
                                        y: 10
                                        minimumValue: 0
                                        value: modelData
                                        maximumValue: 100
                                    }
                                }
                            

                            Untested.

                            how to add more elements

                            Use FirstModel.setNum to modify your list.

                            (Z(:^

                            M 1 Reply Last reply
                            0
                            • sierdzioS sierdzio

                              Ok, so that is a bit wrong.

                              Either change your Model into a proper model (QAbstractItemModel or QListItemModel etc.). Or (easier) set the num property as model, like this:

                              GridView {
                                      width: 300; height: 200
                                      model:  FirstModel.num
                                      delegate: Gauge {
                                          x: 10
                                          y: 10
                                          minimumValue: 0
                                          value: modelData
                                          maximumValue: 100
                                      }
                                  }
                              

                              Untested.

                              how to add more elements

                              Use FirstModel.setNum to modify your list.

                              M Offline
                              M Offline
                              milan
                              wrote on last edited by milan
                              #14

                              @sierdzio. Thank you for your answer. I tried as you suggested with

                              GridView {
                                      width: 300; height: 200
                                      model:  FirstModel.num
                                      delegate: Gauge {
                                          x: 10
                                          y: 10
                                          minimumValue: 0
                                          value: modelData
                                          maximumValue: 100
                                      }
                                  }
                              

                              But I see nothing in the GUI. I will surely try later with QAbstractItemModel you suggested.

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved