在 QML TableView 中显示来自 Python 的 QStandardItemModel

问题描述 投票:0回答:1

我正在尝试使用 QML

TableView
和 Qt for Python / PySide6 在 Qt Quick 中显示非常简单的 2D 数据。这是我想要创建的示例:

enter image description here

在下面的代码中,我向 QML 公开了一个单例对象,它提供了

QStandardItemModel
作为 QObject 属性,但无法显示任何内容。我的上述尝试有什么问题吗?

// Main.qml
import QtQuick
import QtQuick.Window
import QtQuick.Layouts
import QtQuick.Controls
import Qt.labs.qmlmodels
import com.simplified

Window {
    width: 740
    height: 540
    visible: true
    title: "Python log viewer"

    TableView {
        id: log

        anchors.fill: parent

        columnSpacing: 1
        rowSpacing: 1
        clip: true

        model: Simplified.log

        delegate: Rectangle {
            border.width: 1
            clip: true

            Text {
                text: display
                anchors.centerIn: parent
            }
        }
    }
}
# main.py
QML_IMPORT_NAME = "com.simplified"
QML_IMPORT_MAJOR_VERSION = 1

# Core dependencies
from pathlib import Path
import sys

# Package dependencies
from PySide6.QtCore import QObject, Signal, Property, Qt
from PySide6.QtGui import QGuiApplication, QStandardItemModel, QStandardItem
from PySide6.QtQml import QQmlApplicationEngine, QmlElement, QmlSingleton

LOG_ENTRIES = [
    {
        "Timestamp": "2024-07-01 19:16:03.326",
        "Name": "root.child",
        "Level": "DEBUG",
        "Message": "This is a debug message",
    },
    {
        "Timestamp": "2024-07-01 19:16:03.326",
        "Name": "root.child",
        "Level": "INFO",
        "Message": "This is an info message",
    },
]

FIELD_NAMES = ["Timestamp", "Name", "Level", "Message"]

@QmlElement
@QmlSingleton
class Simplified(QObject):
    log_changed = Signal()

    def __init__(self) -> None:
        super().__init__()

        _ = self.log
        self.log_changed.emit()

    @Property(QStandardItemModel, notify=log_changed)
    def log(self):
        lines = LOG_ENTRIES

        table = QStandardItemModel(len(lines), len(FIELD_NAMES))
        table.setHorizontalHeaderLabels(FIELD_NAMES)

        for line in lines:
            row = [QStandardItem(str(line[key])) for key in FIELD_NAMES]
            table.appendRow(row)

        return table

if __name__ == "__main__":
    application = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    qml_file = Path(__file__).resolve().parent / "qml" / "Main.qml"

    engine.load(qml_file)

    if not engine.rootObjects():
        sys.exit(-1)

    engine.singletonInstance("com.simplified", "Simplified")

    sys.exit(application.exec())

python qt qml pyside qtquick2
1个回答
0
投票

您需要存储模型。 QML TableView 不会像

QAbstractItemView
派生类一样拥有该模型。在 TableView 的 QML 实现多次访问之后,从
Simplified.log()
返回的模型将在事件循环中被销毁。在官方示例中检查模型的生命周期。

此外,您将

Simplified.log
属性的类型指定为
QStandardItemModel
,但 QML 引擎的属性类型分派实现并不知道,因为它默认情况下未注册。请参阅参考资料,例如QML 类型系统数据类型转换

以下是固定代码的示例。

@QmlElement
@QmlSingleton
class Simplified(QObject):
    log_changed = Signal()
    def __init__(self):
        super().__init__()
        self.model = None

    @Property(QObject, notify=log_changed)
    def log(self):
        if self.model is None:
            self.model = model = QStandardItemModel()
            for line in LOG_ENTRIES:
                row = [QStandardItem(str(line[key])) for key in FIELD_NAMES]
                model.appendRow(row)
        return self.model
© www.soinside.com 2019 - 2024. All rights reserved.