Quantcast
Channel: Active questions tagged qtquick2 - Stack Overflow
Viewing all articles
Browse latest Browse all 137

Displaying QStandardItemModel from Python in a QML TableView

$
0
0

Please note that versions of this question have been asked before, but the various comments and proposed solutions have not worked. They either cover C++, for which I have tried replicating the solution without success, or more often than not, they are using older versions of Qt Quick and are methods that are no longer workable in the newer versions.


Problem

I am trying to display very simple 2D data in Qt Quick using a QML TableView and Qt for Python / PySide6. Here is an example of what I am looking to create:

enter image description here

This table takes me just a few minutes to create in LabVIEW. However, I am completely at a loss for how to properly do this in QML and with Python using the singleton approach.

What I've read

A pure QML example that kind of works

The official documentation unfortunately highlights the simplest case in which the model is defined purely in QML.

import QtQuickimport QtQuick.Windowimport QtQuick.Layoutsimport QtQuick.Controlsimport Qt.labs.qmlmodelsimport com.simplifiedWindow {    width: 740    height: 540    visible: true    title: "Python log viewer"    TableView {        id: log        anchors.fill: parent        columnSpacing: 1        rowSpacing: 1        clip: true        model: TableModel {            TableModelColumn {                display: "Timestamp"            }            TableModelColumn {                display: "Logger"            }            TableModelColumn {                display: "Level"            }            TableModelColumn {                display: "Message"            }            rows: [                {"Timestamp": "today","Logger": "root","Level": "DEBUG","Message": "This is a debug message"                },                {"Timestamp": "today","Logger": "root","Level": "INFO","Message": "This is an info message"                }            ]        }        delegate: Rectangle {            border.width: 1            clip: true            Text {                text: display                anchors.centerIn: parent            }        }    }}

This looks like:

enter image description here

Of course, the message column needs to be made wider, and I'm not sure how to get header names displayed using this setup, but it at least shows that the rest of the QML is correct and that the issue is with my model.

QML plus Python that doesn't work

The following code should be very close to working, but it does not. I do not know how to amend it to get the table displaying as expected.

// Main.qmlimport QtQuickimport QtQuick.Windowimport QtQuick.Layoutsimport QtQuick.Controlsimport Qt.labs.qmlmodelsimport com.simplifiedWindow {    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.pyQML_IMPORT_NAME = "com.simplified"QML_IMPORT_MAJOR_VERSION = 1# Core dependenciesfrom pathlib import Pathimport sys# Package dependenciesfrom PySide6.QtCore import QObject, Signal, Property, Qtfrom PySide6.QtGui import QGuiApplication, QStandardItemModel, QStandardItemfrom PySide6.QtQml import QQmlApplicationEngine, QmlElement, QmlSingletonLOG_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@QmlSingletonclass 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 tableif __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())

No matter how I've tried building up the items and rows in the QStandardItemModel, I have been unable to get anything to display. I have also tried all sorts of things in the text field item inside the Text component.

Here's a set of commented out code I've tried, amongst many other permutations:

        # table.setItemRoleNames(        #     {i: FIELD_NAMES[i].encode() for i in range(len(FIELD_NAMES))}        # )        # for row_index, line in enumerate(lines):        #     for column_index, key in enumerate(FIELD_NAMES):        #         item = QStandardItem(str(line[key]))        #         table.setItem(row_index, column_index, item)        # for line in lines:        #     row = QStandardItem()        #     for role_index, key in enumerate(FIELD_NAMES):        #         row.setData(str(line[key]), Qt.ItemDataRole + role_index)        #     table.appendRow(row)        # for line in lines:        #     row = QStandardItem()        #     for role_index, key in enumerate(FIELD_NAMES):        #         row.appendColumn([QStandardItem(str(line[key]))])        #     table.appendRow(row)

I have also tried using a combination of the two solutions, trying to provide a list model for the rows of a TableModel, but that property expects a JSON array. I was not able to convert anything in Python to something accepted by the rows property.

Questions

  1. [Primary] What is the simplest, most direct way to display 2D data in a QML TableView from a QStandardItemModel in Python? What is wrong with my above attempt?

  2. [Secondary] Where should I go to learn more about this? The official documentation is close to useless along these lines, and so I'm stuck being in experimental mode just trying things out. Qt also works poorly with QML and the singleton approach in Python, which increases the debugging difficulty.



Viewing all articles
Browse latest Browse all 137

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>