标签:结构 https href model 就是 dup dynamic tree mode
上一次说到用 QQmlApplicationEngine 多次load的方式创建多个一级窗口 详见这里{:target="_blank"},
但是窗口数据需要自己设置, 不如Model设置方式方便, 窗口如果比较复杂, 数据设置起来比较麻烦,而且管理窗口也会比较麻烦.
这里就说说用 Instantiator 这个QML里面的组件, 这个组件是根据模版用来动态创建多个QML组件的
(A Instantiator can be used to control the dynamic creation of objects, or to dynamically create multiple objects from a template.).
只是没想到的是竟然可以来创建多个一级窗口.
先看一下简单的:
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Window 2.3
Instantiator {
id: windowInstantiator
model: ListModel {
id: windowModel
ListElement { title: "Initial Window"; x: -200 }
ListElement { title: "Second Window"; x:300 }
}
delegate: Window {
id: window
visible: true
width: 640
height: 480
x: Screen.width/2 - window.width/2 + model.x
y: Screen.height / 2 - window.height/2
title: model.title
Rectangle {
width: 150
height: 50
Button {
text: qsTr("Duplicate Window")
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
onClicked: windowModel.append({ "title": "Window #" + (windowModel.count +1)})
}
}
}
}
那接下来我们看看如何直接通过Model来控制创建多个窗口, 为了与真实情况接轨, 里面放一个ListView, 视图QML如下:
import QtQuick 2.12
import QtQuick.Controls 2.5
import QtQuick.Window 2.3
import QtQuick.Layouts 1.3
Instantiator {
id: windowInstantiator
model: rootModel
delegate: Window {
id: window
visible: true
width: 640
height: 480
x: Screen.width/2 - window.width/2 + modelData.x
y: Screen.height / 2 - window.height/2
title: modelData.title + " (Window Count: " + count + " )"
ListView{
width: 100; height: 100
id: listView
objectName: "listView"
Layout.fillWidth: true
Layout.fillHeight: true
model: modelData.listModel
delegate: Rectangle {
height: 25
width: 100
Text { text: "hello " + model.name }
}
}
}
}
其中Instantiator的model是 rootModel, 而ListView的Model用的是 listModel数据.
接下来我们看看如何设置数据, 有两种方法:
class WindowModel : public QObject
{
Q_OBJECT
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
Q_PROPERTY(int x READ getX WRITE setX NOTIFY xChanged)
Q_PROPERTY(MyListModel* listModel READ getListModel WRITE setListModel NOTIFY listModelChanged)
public:
explicit WindowModel(QObject *parent = nullptr);
QString title() const;
void setTitle(const QString &title);
MyListModel *getListModel() const;
void setListModel(MyListModel *value);
int getX() const;
void setX(int x);
Q_SIGNALS:
void titleChanged();
void xChanged();
void listModelChanged();
private:
QString _title = "";
int m_x = 0;
MyListModel* m_listModel;
};
然后直接放到QList里面:
//用自己定义Model
WindowModel *win1 = new WindowModel();
win1->setTitle( "First");
win1->setX(-100);
win1->setListModel(model1);
WindowModel *win2 = new WindowModel();
win2->setTitle( "Second");
win2->setX(300);
win2->setListModel(model2);
//QVariantList list;
QList<WindowModel *> winlist;
winlist << win1 << win2;
看了看QHash, 并不能直接在QML里面使用, 可以用QQmlPropertyMap, 则可以在QML里面用modelData.xxx的方式直接调用数据.
//用类似Map结构的QQmlPropertyMap
QQmlPropertyMap hash1;
hash1.insert("title", "First");
hash1.insert("x", QVariant::fromValue(-100));
hash1.insert("listModel", QVariant::fromValue(model1));
QQmlPropertyMap hash2;
hash2.insert("title", "Second");
hash2.insert("x", QVariant::fromValue(300));
hash2.insert("listModel", QVariant::fromValue(model2));
//QVariantList list;
QList<QQmlPropertyMap*> list;
list << &hash1 << &hash2;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("rootModel", QVariant::fromValue(list));
官方说明详见 https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html{:target="_blank"}
https://github.com/cnscud/learn/tree/master/qt/windowByInstantiator{:target="_blank"}
标签:结构 https href model 就是 dup dynamic tree mode
原文地址:https://www.cnblogs.com/cnscud/p/15020549.html