QTableView - Spaltentitel

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mechanicalStore
User
Beiträge: 178
Registriert: Dienstag 29. Dezember 2009, 00:09

Ich suche gerade eine Methode, um die Spaltentitel in einer QTableView zu setzen. Es fällt mir jedoch echt schwer, die PyQt-Doku richtig zu lesen, weil es da eine sehr große Ableitungshierarchie gibt, die (für mich) kaum zu überblicken ist. Weder in QTableView, noch im dahinterliegenden Model QAbstractTableModel finde ich eine Methode, wie die Spaltentitel zu setzen sind. In einem Tutorial https://www.pythonguis.com/tutorials/py ... py-pandas/ ist beschrieben, wie das mit pandas bewerkstelligt wird. Jedoch kenne ich weder pandas bisher, noch will ich nicht ein zusätzliches modul verwenden, nur weil ich das original nicht finde...

Danke und Gruß
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Fuer Qt solltest du in die C++-Dokumentation und deren Beispiele schauen. Da ist zB https://doc.qt.io/qt-6/qtableview.html#horizontalHeader, und da liest man dann https://doc.qt.io/qt-6/qheaderview.html, und da steht dann https://doc.qt.io/qt-6/qabstractitemmod ... HeaderData
mechanicalStore
User
Beiträge: 178
Registriert: Dienstag 29. Dezember 2009, 00:09

Danke für die schnelle Antwort. Aber mein Problem ist damit nicht gelöst, da ich nicht weiß, wie das zu lesen ist, bzw. wie ich da anzusetzen habe. Mir ist nicht mal klar, welches Modul ich dazu importieren muss, noch, wie die Zusammenhänge sind. QHeaderView erbt von QAbstractItemView, beides ist im (Beispiel des besagten Tutorials) nicht existent. Ergo, geht das irgendwo in die Hierarchie ein. Mir fehlt der Gesamtüberblick. Kannst Du zeigen, wie das implementiert werden müsste (im folgenden Beispiel aus dem Tutorial)? Und kurz erklären, wie man durch die Hierarchie lesen muss, um diesen Weg zu finden? Letzteres würde mir auch schon genügen. Für Ersteres wäre das folgende das Beispiel:

Code: Alles auswählen

import sys
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtCore import Qt, QSize
from PyQt6.QtWidgets import QApplication, QMainWindow

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data
        self.labels = ['Spalte-1', 'Spalte-2', 'Spalte-3']
 
    def data(self, index, role):
        if role == Qt.ItemDataRole.DisplayRole:
            return self._data[index.row()][index.column()]

    def rowCount(self, index):
        return len(self._data)

    def columnCount(self, index):
        return len(self._data[0])


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Test")
        self.resize(QSize(400, 300))

        self.table = QtWidgets.QTableView()

        data = [
          [4, 9, 2],
          [1, 0, 0],
        ]

        self.model = TableModel(data)
        self.table.setModel(self.model)
        self.setCentralWidget(self.table)
 
def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()

if __name__ == "__main__":
    main()
Danke und Gruß
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie schon gesagt, Python-Tutorials helfen nicht. Davon gibt es zu wenig. Das hier ist aus der ersten verlinkten Seite erreichbar, unter den Beispielen: https://code.qt.io/cgit/qt/qtbase.git/t ... .cpp?h=6.5

Du musst die echte Qt-Dokumentation lesen. Der ganze Python-Kram beschaeftigt sich hauptsaechlich mit den leichten und systematischen Unterschieden zwischen Python und C++.
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@mechanicalStore: Die Importe sind ziemlich inkonsistent wann etwas direkt aus den Untermodulen von PyQt importiert wird und wann etwas über das Untermodul referenziert wird. Wonach wurde das entschieden?

Bei `data()` sollte man in jedem Fall explizit etwas zurückgeben.

Warum wird `super()` unterschiedlich verwendet? In Python 3 macht es in der Regel keinen Sinn das immer noch wie in Python 2 zu verwenden.

Wenn die Spaltennamen Bestandteil des Models sind, dann muss man doch bloss `headerData()` entsprechend implementieren (ungetestet):

Code: Alles auswählen

import sys

from PyQt6.QtCore import QAbstractTableModel, QSize, Qt
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView


class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super().__init__()
        self._data = data
        self.labels = ["Spalte-1", "Spalte-2", "Spalte-3"]

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.labels[section]
        
        return None

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self._data[index.row()][index.column()]

        return None

    def rowCount(self, _index):
        return len(self._data)

    def columnCount(self, _index):
        return len(self._data[0])


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__(windowTitle="Test")
        self.resize(QSize(400, 300))
        self.table = QTableView()
        self.table.setModel(TableModel([[4, 9, 2], [1, 0, 0]]))
        self.setCentralWidget(self.table)


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
mechanicalStore
User
Beiträge: 178
Registriert: Dienstag 29. Dezember 2009, 00:09

Hallo __blackjack__,

all diese Umstände, die Du anmerkst, sind copy&paste aus dem besagten Tutorial (von Martin Fitzpatrick), womit klar ist, dass man sich auf sowas nicht verlassen sollte. Er hat sogar ein Buch geschrieben, das er auf der Seite bewirbt (wo quasi alles 1:1 noch mal drin steht)...
Zumindest habe ich kapiert, wie die Methode headerData im von __deets__ erwähnten Link zu interpretieren ist.
Wegen copy&paste sind mir die von Dir erwähnten Dinge (voererst) gar nicht aufgefallen (bzw da es eh nur reines Probieren war, habe ich das ignoriert), danke dafür, das Feedback ist sehr hilfreich.
Was eigenartig ist, dass es die in Deinem Beispiel erwähnten Qt.Horizontal und Qt.DisplayRole direkt nicht gibt (obwohl es in von __deets__ erwähnter Qt original-Doku so steht). Qt.Orientation.Horizontal ist der funktionierende Ausdruck (wobei das ja aus der Originaldoku noch hervor geht), aber weiter ist nur Qt.ItemDataRole.DisplayRole funktionierend, was aus der Qt original-Doku nicht hervor geht (kommt eben aus dem Tutorial, aber woher stammt es dann, wie kommt man darauf?).

Zuletzt die Frage, was hat es mit PyQt6 und PySide6 auf sich? Was sollte man favorisieren?

Danke und Gruß
Benutzeravatar
snafu
User
Beiträge: 6870
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mechanicalStore hat geschrieben: Montag 28. August 2023, 10:01 In einem Tutorial https://www.pythonguis.com/tutorials/py ... py-pandas/ ist beschrieben, wie das mit pandas bewerkstelligt wird. Jedoch kenne ich weder pandas bisher, noch will ich nicht ein zusätzliches modul verwenden, nur weil ich das original nicht finde...
Wie kommst du darauf, dass zwingend ``pandas`` als Backend benutzt werden muss, nur um an Spaltenüberschriften zu kommen? Wie du die Überschriften implementierst, liegt doch bei dir. Denkbar wäre z.B. ein Dictionary und das wiederum gehört zu den absoluten Basics in Python. Sollte dir das nicht bekannt sein, dann gehst du vielleicht nochmal 2 Schritte zurück und liest erstmal ein Python-Tutorial, bevor du dich dann irgendwann mit Qt-Models beschäftigst...

Übrigens, die entsprechende Methode auf dem Model heißt ``headerData()`` und die muss für jeden Index die jeweils passende Überschrift liefern. Also nicht alles in einem Rutsch, sondern immer nur das, was Qt gerade anfragt. Ist ja auch in dem von dir verlinkten Tutorial ziemlich am Ende genau so beschrieben. Grundsätzlich könntest du den dortigen Code sogar als Grundgerüst benutzen.

EDIT: Ein Wörterbuch eigentlich auch erst in "neueren" Python-Versionen, wo man sich auf die Reihenfolge der Keys verlassen kann (sofern man die nicht nachträglich verändert). Der klassische Ansatz wäre eine separate Liste mit den Überschriften, wie hier ja auch schon gezeigt wurde. Will man die Daten und Überschriften zusammenhalten, aber auf ein Wörterbuch verzichten, wäre auch eine verschachtelte Liste denkbar, wo das erste Element die jeweilige Überschrift darstellt. Da muss man selbst entscheiden, womit man besser umgehen kann.

Mit der verschachtelten Liste meine ich übrigens etwas in dieser Art:

Code: Alles auswählen

self.data = [
    ("SpalteA", [4, 9, 2]),
    ("SpalteB", [1, 0, 15])
]
mechanicalStore
User
Beiträge: 178
Registriert: Dienstag 29. Dezember 2009, 00:09

Hallo Snafu,

danke für Deine Anmerkungen.
snafu hat geschrieben: Montag 28. August 2023, 21:35 ... Denkbar wäre z.B. ein Dictionary und das wiederum gehört zu den absoluten Basics in Python. Sollte dir das nicht bekannt sein, dann gehst du vielleicht nochmal 2 Schritte zurück und liest erstmal ein Python-Tutorial, bevor du dich dann irgendwann mit Qt-Models beschäftigst...
Ich denke, die Basics sind mir bekannt... Bei der Frage ging es aber nicht um die Datenstruktur, mit der die Methode gefüttert wird, sondern um den gesuchten Methodennamen:
Übrigens, die entsprechende Methode auf dem Model heißt ``headerData()`` und die muss für jeden Index die jeweils passende Überschrift liefern. Also nicht alles in einem Rutsch, sondern immer nur das, was Qt gerade anfragt.
Daher überrascht es, warum Du ein Dictionary erwähnst. Da die Daten im Model nach Index abgefragt werden, hätte ich ein Dictionary mit durchnummerierten Keys, was durch eine Liste viel einfacher zu implementieren ist. Oder meintest Du was Anderes?
Ist ja auch in dem von dir verlinkten Tutorial ziemlich am Ende genau so beschrieben. Grundsätzlich könntest du den dortigen Code sogar als Grundgerüst benutzen.
Ich hab es als Minimal-Beispiel genutzt, um meine Frage zu stellen. Bisher habe ich keine GUI gebraucht. Seit einiger Zeit wollte ich mal etwas mit GUIs machen. Nachdem __deets__ empfohlen hatte, lieber Qt statt Wx zu nehmen, hatte ich mich darauf eingelassen. Da ich nun etwas Zeit habe, wollte ich mir das anschauen. Der Informationsgehalt im Netz ist groß. Was Qt betrifft, stehe ich am Anfang...
EDIT: Ein Wörterbuch eigentlich auch erst in "neueren" Python-Versionen, wo man sich auf die Reihenfolge der Keys verlassen kann (sofern man die nicht nachträglich verändert). Der klassische Ansatz wäre eine separate Liste mit den Überschriften, wie hier ja auch schon gezeigt wurde. Will man die Daten und Überschriften zusammenhalten, aber auf ein Wörterbuch verzichten, wäre auch eine verschachtelte Liste denkbar,
Ok, das war der Grund für das Dictionary. Trifft in meinem Fall allerdings weniger zu, denn die Daten kommen von SQLAlchemy aus einer Datenbank,da macht es keinen Sinn, das vorher zusammen zu bauen. Daher das getrennte Setzen der Überschriften.

Danke und Gruß
Antworten