Using same qml for multiple instantiation
-
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.
-
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 } -
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.
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.
-
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.
@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.
-
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 }@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
-
@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
-
@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."
-
@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. -
@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.@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) -
What is FirstModel?
-
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.
-
Ok, so that is a bit wrong.
Either change your Model into a proper model (QAbstractItemModel or QListItemModel etc.). Or (easier) set the
numproperty 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.setNumto modify your list. -
Ok, so that is a bit wrong.
Either change your Model into a proper model (QAbstractItemModel or QListItemModel etc.). Or (easier) set the
numproperty 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.setNumto modify your list.@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.