Hello I am using Model class to supply items for lists and comboboxes. The problem is that I use the setContextProperty() function every time for each element. I'm looking for a solution where all elements(list and comboboxes) use the same ContextProperty. Furthermore with this way I guess JSON files can be loaded dynamically instead of loading all of them at the beginning.
main.py
class Model(QAbstractListModel, QObject):
""" it reads JSON file, that is given as argument,
and creates the model"""
if __name__ == "__main__":
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
model1 = Model("file1.json")
model2 = Model("file2.json")
model3 = Model("file3.json")
model4 = Model("file4.json")
model5 = Model("file5.json")
engine.rootContext().setContextProperty("model1", model1)
engine.rootContext().setContextProperty("model2", model2)
engine.rootContext().setContextProperty("model3", model3)
engine.rootContext().setContextProperty("model4", model4)
engine.rootContext().setContextProperty("model5", model5)
engine.rootContext().setContextProperty("applicationDirPath", os.path.dirname(__file__))
engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec())
You can create a QObject that exposes all the models as a property list and then use a Repeater to dynamically create the comboboxes.
The following is a demo:
import os
import sys
from pathlib import Path
from PySide6.QtCore import Property, QCoreApplication, QObject, Qt, QUrl, Signal
from PySide6.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PySide6.QtQml import QQmlApplicationEngine
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class Model(QStandardItemModel):
def __init__(self, values, parent=None):
super().__init__(parent)
for value in values:
item = QStandardItem(value)
self.appendRow(item)
class Manager(QObject):
models_changed = Signal(name="modelsChanged")
def __init__(self, parent=None):
super().__init__(parent)
self._models = []
@Property("QVariantList", notify=models_changed)
def models(self):
return self._models
def append_model(self, model):
self._models.append(model)
self.models_changed.emit()
def main():
app = QGuiApplication(sys.argv)
manager = Manager(app)
manager.append_model(Model(["item11", "item12", "item13"]))
manager.append_model(Model(["item21", "item22", "item23"]))
manager.append_model(Model(["item31", "item32", "item33"]))
manager.append_model(Model(["item41", "item42", "item43"]))
engine = QQmlApplicationEngine()
context = engine.rootContext()
context.setContextProperty("applicationDirPath", os.fspath(CURRENT_DIRECTORY))
context.setContextProperty("managerModel", manager)
filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
url = QUrl.fromLocalFile(filename)
def handle_object_created(obj, obj_url):
if obj is None and url == obj_url:
QCoreApplication.exit(-1)
engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
engine.load(url)
sys.exit(app.exec())
if __name__ == "__main__":
main()
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
width: 640
height: 480
visible: true
ColumnLayout {
anchors.centerIn: parent
Repeater {
id: repeater
model: managerModel.models
ComboBox {
model: modelData
textRole: "display"
Layout.fillWidth: true
}
}
}
}
Side note: A QAbstractListModel is a QObject so the double inherence is useless so you should change it to: class Model(QAbstractListModel):