[英]QT/QML Data Model
我想創建一個 Qt 數據 model,其結構如下所示,用於 Python 和 QML。如果在 Python 或 QML 中更改、添加或刪除了任何值或鍵(我需要在另一側更新 QML 值)或蟒蛇)。 理想情況下,這將是 ListView 中使用的 model,我只會顯示 ListView 的某些字段。 但我會使用這個數據 model 來存儲我所有的信息。 當在 Python 中對 memory 執行測試時,我想將該測試日志信息寫入此數據 model 並在 QML 中顯示。我已經閱讀了 QAbstractListModel,但我不確定我是否可以制作嵌套對象或列表以及它們是否會自動更新與否。
System: {
Processor: {
name: 'Processor',
description: 'Intel i7 6600k',
iconSource: '/resources/images/chip.svg',
progressValue: 100,
pageSource: '/resources/qml/Processor.qml',
details: {
"badge": "Intel® Core i5 processor",
"cache": "6144 KB",
"clock": "4200000"
}
testLog: [
'Starting Cpu Test',
'Detected Intel CPU',
'Performing intense calculations',
'Processing calculations still',
'Cleaning up',
'Test Passed'
]
}
Memory: {
name: 'Memory',
description: 'Kingston 16GB DDR3',
iconSource: '/resources/images/ram.svg',
progressValue: 50,
pageSource: '/resources/qml/Processor.qml',
details: {
"device_locator_string": "ChannelB-DIMM1",
"device_set": 0,
"error_handle": 65534,
"extended_size": 0,
"form_factor": "Unknown"
},
testLog: [
'Starting Memory Test',
'Detected 2 x RAM modules',
'Performing intense calculations',
'Processing calculations still',
'Cleaning up',
'Test Failed'
]
}
}
在這種情況下有幾種選擇,例如:
基於 QAbstractItemModel 創建一個 model,您可以在其中通過角色提供屬性。
創建一個 QObject 設備,它具有所需的屬性作為 qproperties,並通過與來自另一個 QObject 的信號關聯的 qproperty 公開它,QObject 設備列表並將該列表用作 model。
創建一個 model 作為 QAbstractListModel(或 QStandardItemModel)並通過角色公開 QObject。
創建一個 QObject,通過 ListProperty 公開 QObjects Device 列表。
在這種情況下,我選擇了第一個演示選項:
主程序
from dataclasses import dataclass
import sys
from typing import Callable
from PySide2.QtCore import (
Property,
QCoreApplication,
QObject,
QVariantAnimation,
Qt,
QUrl,
)
from PySide2.QtGui import QGuiApplication, QStandardItem, QStandardItemModel
from PySide2.QtQml import QQmlApplicationEngine
@dataclass
class item_property:
role: int
function: Callable = None
def __call__(self, function):
self.function = function
return self
class item_property_impl(property):
def __init__(self, role, function):
super().__init__()
self._role = role
self._function = function
def __get__(self, obj, type=None):
if obj is None:
return self
if hasattr(obj, "_initial"):
obj.setData(self._function(obj), self._role)
delattr(obj, "_initial")
return obj.data(self._role)
def __set__(self, obj, value):
obj.setData(value, self._role)
class ItemMeta(type(QStandardItem), type):
def __new__(cls, name, bases, attrs):
for key in attrs.keys():
attr = attrs[key]
if not isinstance(attr, item_property):
continue
new_prop = item_property_impl(attr.role, attr.function)
attrs[key] = new_prop
if not hasattr(cls, "attrs"):
cls._names = []
cls._names.append(key)
obj = super().__new__(cls, name, bases, attrs)
return obj
def __call__(cls, *args, **kw):
obj = super().__call__(*args, **kw)
obj._initial = True
for key in cls._names:
getattr(obj, key)
return obj
class Item(QStandardItem, metaclass=ItemMeta):
pass
keys = (b"name", b"description", b"icon", b"progress", b"source", b"details", b"log")
ROLES = (
NAME_ROLE,
DESCRIPTION_ROLE,
ICON_ROLE,
PROGRESS_ROLE,
SOURCE_ROLE,
DETAILS_ROLE,
LOG_ROLE,
) = [Qt.UserRole + i for i, _ in enumerate(keys)]
class Device(Item):
@item_property(role=NAME_ROLE)
def name(self):
return ""
@item_property(role=DESCRIPTION_ROLE)
def description(self):
return ""
@item_property(role=ICON_ROLE)
def icon(self):
return ""
@item_property(role=PROGRESS_ROLE)
def progress(self):
return 0
@item_property(role=SOURCE_ROLE)
def source(self):
return ""
@item_property(role=DETAILS_ROLE)
def details(self):
return dict()
@item_property(role=LOG_ROLE)
def log(self):
return list()
class DeviceManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._model = QStandardItemModel()
self._model.setItemRoleNames(dict(zip(ROLES, keys)))
def get_model(self):
return self._model
model = Property(QObject, fget=get_model, constant=True)
def add_device(self, *, name, description, icon, progress, source, details, log):
dev = Device()
dev.name = name
dev.description = description
dev.icon = icon
dev.progress = progress
dev.source = source
dev.details = details
dev.log = log
self.model.appendRow(dev)
return dev
def main():
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
manager = DeviceManager()
engine.rootContext().setContextProperty("device_manager", manager)
url = QUrl("main.qml")
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)
processor = manager.add_device(
name="Processor",
description="Intel i7 6600k",
icon="/resources/images/chip.svg",
progress=10,
source="resources/qml/Processor.qml",
details={
"badge": "Intel® Core i5 processor",
"cache": "6144 KB",
"clock": "4200000",
},
log=[
"Starting Cpu Test",
"Detected Intel CPU",
"Performing intense calculations",
"Processing calculations still",
"Cleaning up",
"Test Passed",
],
)
memory = manager.add_device(
name="Memory",
description="Kingston 16GB DDR3",
icon="/resources/images/ram.svg",
progress=50,
source="resources/qml/Memory.qml",
details={
"device_locator_string": "ChannelB-DIMM1",
"device_set": 0,
"error_handle": 65534,
"extended_size": 0,
"form_factor": "Unknown",
},
log=[
"Starting Memory Test",
"Detected 2 x RAM modules",
"Performing intense calculations",
"Processing calculations still",
"Cleaning up",
"Test Failed",
],
)
def update_progress(value):
processor.progress = value
animation = QVariantAnimation(
startValue=processor.progress, endValue=100, duration=3 * 1000
)
animation.valueChanged.connect(update_progress)
animation.start()
ret = app.exec_()
sys.exit(ret)
if __name__ == "__main__":
main()
主要.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
id: root
visible: true
width: 400
height: 400
ListView {
id: view
property url currentSource: ""
model: device_manager.model
width: parent.width / 2
height: parent.height
spacing: 10
clip: true
flickableDirection: Flickable.VerticalFlick
boundsBehavior: Flickable.StopAtBounds
currentIndex: -1
ScrollBar.vertical: ScrollBar {
}
highlight: Rectangle {
color: "lightsteelblue"
radius: 5
}
delegate: Rectangle {
id: rect
color: "transparent"
border.color: ListView.isCurrentItem ? "red" : "green"
height: column.height
width: ListView.view.width
Column {
id: column
Text {
text: model.name
}
ProgressBar {
from: 0
to: 100
value: model.progress
}
Label {
text: "Log:"
font.bold: true
font.pointSize: 15
}
Text {
text: model.log.join("\n")
}
}
MouseArea {
anchors.fill: parent
onClicked: {
rect.ListView.view.currentIndex = index;
rect.ListView.view.currentSource = model.source;
}
}
}
}
Rectangle {
x: view.width
width: parent.width / 2
height: parent.height
color: "salmon"
Loader {
anchors.centerIn: parent
source: view.currentSource
}
}
}
處理器.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
Rectangle{
color: "red"
width: 100
height: 40
Text{
text: "Processor"
anchors.centerIn: parent
}
}
Memory.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
Rectangle{
color: "blue"
width: 100
height: 40
Text{
text: "Memory"
anchors.centerIn: parent
}
}
├── main.py
├── main.qml
└── resources
└── qml
├── Memory.qml
└── Processor.qml
我想創建一個具有如下結構的 Qt 數據 model 用於 Python 和 ZC477ABFB2FD4959A20ZD5.E0 如果在 Python 或 QML 中更改、添加或刪除任何值或鍵,我需要在另一側(QML 或 Python)更新這些值。 理想情況下,這將是 ListView 中使用的 model,我只會顯示 ListView 的某些字段。 但我會使用這些數據 model 來存儲我的所有信息。 當對 Python 中的 memory 執行測試時,我想將該測試日志信息寫入此數據 model 並在 ZC4DZ7AB02FD4444444D4DZ7AB02FD4 中顯示我已經閱讀了 QAbstractListModel,但我不確定我是否可以制作嵌套對象或列表以及它們是否會自動更新。
System: {
Processor: {
name: 'Processor',
description: 'Intel i7 6600k',
iconSource: '/resources/images/chip.svg',
progressValue: 100,
pageSource: '/resources/qml/Processor.qml',
details: {
"badge": "Intel® Core i5 processor",
"cache": "6144 KB",
"clock": "4200000"
}
testLog: [
'Starting Cpu Test',
'Detected Intel CPU',
'Performing intense calculations',
'Processing calculations still',
'Cleaning up',
'Test Passed'
]
}
Memory: {
name: 'Memory',
description: 'Kingston 16GB DDR3',
iconSource: '/resources/images/ram.svg',
progressValue: 50,
pageSource: '/resources/qml/Processor.qml',
details: {
"device_locator_string": "ChannelB-DIMM1",
"device_set": 0,
"error_handle": 65534,
"extended_size": 0,
"form_factor": "Unknown"
},
testLog: [
'Starting Memory Test',
'Detected 2 x RAM modules',
'Performing intense calculations',
'Processing calculations still',
'Cleaning up',
'Test Failed'
]
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.