QML 的 PySide6 后端是否有更简洁的方法?
Is there a cleaner way for backend in PySide6 for QML?
您好,我正在使用 Model class 为列表和组合框提供项目。问题是我每次都对每个元素使用 setContextProperty() 函数。我正在寻找一种解决方案,其中所有元素(列表和组合框)都使用相同的 ContextProperty。此外,我猜 JSON 文件可以动态加载,而不是一开始就加载所有文件。
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())
您可以创建一个将所有模型公开为 属性 列表的 QObject,然后使用 Repeater 动态创建组合框。
以下为演示:
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
}
}
}
}
旁注:QAbstractListModel 是一个 QObject,因此双重继承是无用的,因此您应该将其更改为:class Model(QAbstractListModel):
您好,我正在使用 Model class 为列表和组合框提供项目。问题是我每次都对每个元素使用 setContextProperty() 函数。我正在寻找一种解决方案,其中所有元素(列表和组合框)都使用相同的 ContextProperty。此外,我猜 JSON 文件可以动态加载,而不是一开始就加载所有文件。
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())
您可以创建一个将所有模型公开为 属性 列表的 QObject,然后使用 Repeater 动态创建组合框。
以下为演示:
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
}
}
}
}
旁注:QAbstractListModel 是一个 QObject,因此双重继承是无用的,因此您应该将其更改为:class Model(QAbstractListModel):