QTableModel/View arbeitet unerwartet

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# -- import --
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

# Model
class Model(QAbstractTableModel):
    def __init__(self, parent=None):
        super(Model, self).__init__(parent)

    def rowCount(self, parent):
        return 10

    def columnCount(self, parent):
        return 2

    def headerData(self, section, orientation, role):
        return "TestHeader"

    def data(self, index, role):
        return str(index.row()) + " x " + str(index.column())

# Window / View
class MV(QDialog):
    def __init__(self, parent=None):
        super(MV, self).__init__(parent)

        # View & Model
        view = QTableView()
        model = Model()
        view.setModel(model)

        # Layout
        layout = QVBoxLayout()
        layout.addWidget(view)
        self.setLayout(layout)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    screen = MV()
    screen.show()
    sys.exit(app.exec_())
Anhänge kann man hier scheinbar nicht einfüngen, sonst würde ich euch zeige, wie das bei mir aussieht.
1.
Problem ist, dass ich keine Header in der Tabelle habe. Laut Doku sollte headers() aber implementiert werden.

2.
Dann sind da Vierecke (vermtulich Checkboxes) in jeder Zelle.

3.
Weiteres Problem ist, dass das TableWidget selbst horizontal größer ist, als die darin enthaltenen zwei Spalten. Sieht unschön aus.
Zuletzt geändert von Anonymous am Dienstag 27. Januar 2015, 22:49, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@MoonKid: Die fehlenden Kopfzeile und -spalte sowie die Checkboxen liegen daran das Du `role` nicht berücksichtigst. Du gibst die jeweiligen Werte ja für *jede* Rolle zurück. Da könnte sonstwas passieren bis hin zum Programmabsturz vermute ich mal.

Zur Unschönheit: Da schlägt die `QTableView`-Dokumentation zum Beispiel vor die letzte Zeile/Spalte automatisch auszudehnen. Also für die Zeilen zum Beispiel mit ``view.horizontalHeader().setStretchLastSection(True)``.
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Ich finde in der Doku dazu keinen Hinweis. Hast du ne andere?

Ah... unter Visual Appearance (leider nicht verlinkbar).
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

MoonKid hat geschrieben:Problem ist, dass ich keine Header in der Tabelle habe. Laut Doku sollte headers() aber implementiert werden.
Probier das mal:

Code: Alles auswählen

    def headerData(self, section, orientation, role):
        return QVariant()
In Qt hat ein leeres QVariant oftmals eine ähnliche Bedeutung wie ein None in Python.
MoonKid hat geschrieben:Dann sind da Vierecke (vermtulich Checkboxes) in jeder Zelle.
Du solltest in der Methode data immer erst die Variable role prüfen und keine Strings zurückgeben, sondern QVariant. Ein Check auf index.isValid() kann auch erforderlich sein:

Code: Alles auswählen

    def data(self, index, role):
        if index.isValid() and role == Qt.DisplayRole:
            return QVariant( str(index.row()) + " x " + str(index.column()) )
        else:
            return QVariant()
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

MoonKid hat geschrieben:Problem ist, dass ich keine Header in der Tabelle habe. Laut Doku sollte headers() aber implementiert werden.
Oder so

Code: Alles auswählen

        view = QTableView()
        view.verticalHeader().setVisible(False)
        view.horizontalHeader().setVisible(False)
        model = Model()
        view.setModel(model)
a fool with a tool is still a fool, www.magben.de, YouTube
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@MoonKid: auch hier gilt wie in allen Pythonprogrammen: keine Sternchenimporte und Stringformatierung verwenden:

Code: Alles auswählen

QVariant("%d x %d" % (index.row(), index.column()))
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Sirius3 hat geschrieben:keine Sternchenimporte und Stringformatierung verwenden
Dafür solltet ihr wirklich im Wiki irgendwelche Kurz-Erläuterungen anlegen, auf die hier für Newbies dann verlinken könnt. ;) Was zum Geier sind Stringformatierungen hier genau bzw. was ist daran falsch?
BlackJack

@MoonKid: An Stringformatierung ist nichts falsch, im Gegenteil. Das ist der ``%``-Operator auf Zeichenketten beziehungsweise die `format()`-Methode.
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Die Qt Doku ist wirklich grauenvoll. Genau solche Detailaspekte sind dort nicht erklärt bzw. über zich Klassenbeschreibungen verteilt.
Es wird nicht erklärt, wie diese einzelnen Methoden implementiert werden sollten bzw. worauf im Detail geachtet werden muss. Woher z.B. soll man "index.IsValid()" wissen? Wie kommt ihr auf sowas? Woher soll ich wissen was ich mit 'role' machen soll? Das Konzept dazu wird nicht erklärt und der Datentyp ist ein "int" (weil es ja nur eine C++ Ref dazu gibt). Nebenbei erschwert hier Python selbst auch die Arbeit, weil ich in meinem eigenen Code die Datentypen der Parameter nicht sehen kann. Da steht nur "role" und nicht "int role" (obwohl der Datentyp eigentlich 'Qt::​ItemDataRole' ist) oder ähnliches. Kann mir doch das nicht immer merken, oder in der grotting Qt-Doku die Datentypen nachschlagen.
BlackJack hat geschrieben:@MoonKid: An Stringformatierung ist nichts falsch, im Gegenteil. Das ist der ``%``-Operator auf Zeichenketten beziehungsweise die `format()`-Methode.
Sorry, kann dir nicht folgen. Ich dachte es wäre falsch? Und was ist mit '%'?
BlackJack

@MoonKid: Interessant, ich finde die Qt-Dokumentation ziemlich gut. Natürlich sind die Details bei den Klassen die sie betreffen dokumentiert, wo denn auch sonst? Darüber hinaus gibt es für die wichtigen Themen Einführungen. Zum Beispiel ist in der Dokumentation zum `QTableView` ziemlich am Anfang der Beschreibung ein Link zum allgemeinen Text zu „Model/View Programming” wo grundlegende Sachen wie zum Beispiel auch die Rollen erklärt werden. Da steht zum Thema `data()` und `headerData()` auch im Text und im Beispielcode das auf `index.isValid()` getestet wird und das der Text nur bei der entsprechenden Rolle für die Textanzeige zurückgegeben wird. Wenn Du diese grundlegenden Informationen bei der Dokumentation vom `QTableView` erwartet hättest, dann müsste ja exakt der selbe, ellenlange Text bei jeder View-Klasse aus dem Rahmenwerk wiederholt werden statt bei jeder einen Link darauf zu haben. Das wäre ziemlich redundant und letztendlich auch nervig diesen Riesenbatzen Text immer wieder zu haben, denn wenn man erst einmal drin ist in der Qt-Programmierung dann würden die Details die einen dann noch bei den Klassen interessieren in diesen ganzen Grundlagentexten untergehen.

Zusätzlich gibt es noch ein Model View Tutorial und 20 Beispielprogramme zum Thema „Model and Views” in der Qt4-Dokumentation. Gibt's das alles in der Qt5-Dokumentation nicht mehr?

Zum Thema Zeichenketten zusammenbauen: Mit `str()` und ``+`` Werte und literale Teile zusammenzustückeln ist schlecht lesbar und unflexibel. Stattdessen sollte man die `format()`-Methode, oder den ``%``-Operator verwenden. Wobei `format()` die modernere und etwas mächtigere Variante ist.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

MoonKid hat geschrieben:Die Qt Doku ist wirklich grauenvoll.
Da stehst du mit deiner Meinung wahrscheinlich recht alleine da. Ich würde eher behaupten, dass sie zu einer der besten Dokumentationen gehört. Sehr gut strukturiert, sehr gut geschrieben und recht detailreich. Viel besser geht es kaum.
Das Leben ist wie ein Tennisball.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

MoonKid hat geschrieben:Woher z.B. soll man "index.IsValid()" wissen? Wie kommt ihr auf sowas? Woher soll ich wissen was ich mit 'role' machen soll?
Qt ist nicht einfach nur irgendeine Python-API, die Du Dir mal eben für ein Programmierproblem reinziehst. Qt ist eine Plattform. Es dauert deutlich länger Qt zu lernen, als Python zu lernen (wenn man schon mal Programmieren kann). Es wird aber deutlich besser, wenn Du Dir erstens Zeit dafür nimmst und zweitens didaktisch aufbereitete Doku benutzt, d.h. ein Buch dazu liest. Zu Qt5 gibt's leider gar keine Bücher. Folgendes PyQt4 Buch hat mir sehr gefallen:
Rapid GUI Programming with Python and Qt
Das Buch ist nicht mehr aktuell, die Grundlagen von Qt haben sich aber nicht geändert.

Hinzu kommt noch:
  • QAbstractTableModel und insbesondere QAbstractItemModel (für QTreeView) sind sehr viel schwieriger zu implementieren, als z.B. die entsprechenden Java-Swing Klassen. Trolltech hätte es da auch einfacher machen können.
  • Es hilft sehr PyQt zu verstehen, wenn mann C++/Qt kennt.
PS: alles was zur String-Formatierung gesagt wurde ist richtig, hat aber nichts mit Deinem Problem zu tun. Alter Trick für mündliche Prüfungen: rede über das was Du gut kannst.
a fool with a tool is still a fool, www.magben.de, YouTube
MoonKid
User
Beiträge: 105
Registriert: Mittwoch 10. Dezember 2014, 16:24

Früher (zu C++ Qt2/3-Zeiten) gab es noch hübsche grafische Darstellungen der Vererbugnshirarchien der Qt-Klassen. ;)

Es ist jedenfalls interessant, eure Sicht der Dinge zu sehen.

Meinem Empfinden nach, merkt man der Doku an, dass eine Firma mit kommerziellen Interessen dahinter steckt. Die Doku setzt einfach primär darauf, die Fähigkeiten schön darzustellen und stellt das "Lernen" des Entwicklers dem hinten an. Tiefere Themen sind nur in kostenpflichtigen Dokus (Bücher) zu finden.

Bei dieser Model/View Einführung wird gleich zu Beginn ein FileSystemModel gezeigt. Wozu? Unsinn, das hilft überhaupt nicht dem Verständnis.
Dem Verständnis würden zwei Dinge helfen:
1. Die allgemeine Erklärung des MVC eleminieren und auf externe Quellen verweisen. Wer das nutzt, sollte das Pattern in seiner Reihnform verstanden haben. Das hat in der Qt-Doku nix zu suchen. Die Doku geht viel zu sehr davon aus, dass der Entwickler das MVC noch nicht so ganz kennt.
2. Es sollte gleich zu Beginn ein eigenes View und Model (also jeweils QAbstract*) aufgebaut werden, um daran die Feinheiten und Besonderheiten darzustellen. Das es schon davon abgeleitete Klassen für Standardfälle gibt, kann man danach anbauen und ist für das Verständnis aber nicht relevant.

Desweiteren wird unberücksichtigt gelassen, dass das MVC-Pattern ein Idealbild eine Utiopie darstellt, die unterschiedlich interpretiert und implementiert werden kann. Sicher ist meine Interpretation pingelich und fundamentalistisch - aber der Sache bin ich mir bewusst. Ich erwarte auch nicht das Qt oder andere Libs das Pattern so implementieren, sondern ihre eigene Interpretation davon bringen.

Beispiel: Alleine das Qt das Pattern "vollständig" implementiert, ist ein Widerspruch in sich. Wenn ich den Presentation Layer (also Qt) austauschen möchte, zieht das auch Änderungen im Application Layer (da wo die Model-Klassen sind) nach sich. Das ist kein MVC, jedoch erwarte ich das auch nicht. Das es nur eine Annährung ist, war mir immer klar.

Aber das sind alles Apsekte und Sichtweisen, die in der Doku zu wenig Berücksichtigung finden. Es wird dort zu wenig auf Grundkonzepte und Designentscheidungen (warum ist das so in Qt) eingegangen.

Aber erstmal soweit Danke für eure Einblicke. Ich werd mich weiter reinfuchsen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

MoonKid hat geschrieben:Früher (zu C++ Qt2/3-Zeiten) gab es noch hübsche grafische Darstellungen der Vererbugnshirarchien der Qt-Klassen. ;)
Ja, dann ist die aktuelle Dokumentation natürlich zum Wegwerfen :lol:
MoonKid hat geschrieben:Meinem Empfinden nach, merkt man der Doku an, dass eine Firma mit kommerziellen Interessen dahinter steckt. Die Doku setzt einfach primär darauf, die Fähigkeiten schön darzustellen und stellt das "Lernen" des Entwicklers dem hinten an. Tiefere Themen sind nur in kostenpflichtigen Dokus (Bücher) zu finden.
Da steckt aber schon irgendwie ein Widerspruch in deiner Aussage. Es soll ein Produkt verkauft werden und dann macht man es den Anwendern möglichst schwer dies zu verwenden. Ja, das scheint mir eine ganz logische Schlussfolgerung ;-) Aber mal ganz von dem Punkt abgesehen: Eine Dokumentation ist kein Tutorial. Das wäre ja grausam, wenn jede Klasse aus Qt im Tutorial-Stil beschrieben werden würde, da wird man als Entwickler doch verrückt beim lesen. Wenn man die Grundlagen des Toolkits beherrscht, dann erschließt sich die Verwendung einer Klasse von alleine.
MoonKid hat geschrieben:Beispiel: Alleine das Qt das Pattern "vollständig" implementiert, ist ein Widerspruch in sich. Wenn ich den Presentation Layer (also Qt) austauschen möchte, zieht das auch Änderungen im Application Layer (da wo die Model-Klassen sind) nach sich. Das ist kein MVC, jedoch erwarte ich das auch nicht. Das es nur eine Annährung ist, war mir immer klar.
Qt ist nicht "nur" ein Framework zur Darstellung, Qt möchte alles aus einer Hand bieten. Dazu gehören Model, View Controler, aber auch Tools wie der Designer oder der Creator. Sieh Qt nicht als ein Framework zu Darstellung, sieh es als eigenen Ökosystem oder als eigene Sprache.
Das Leben ist wie ein Tennisball.
BlackJack

@MoonKid: Das ist in der Hauptsache eine Referenzdokumentation angereichert mit ein paar Tutorials. Das ist doch bei sehr vielen Rahmenwerken und Standardbibliotheken so. Bei Python oder Java sieht das doch zum Beispiel ähnlich aus. Wobei es sicher nicht nur kostenpflichtige Bücher gibt. Neben Wiki und Tutorials von ”extern” kann man heutzutage ja auch viele Detaillösungen in Foren und Seiten wie StackExchange finden ohne Geld ausgeben zu müssen.

Mit dem `QFileSystemModel` kann man ganz am Anfang ein sehr einfaches Beispiel zusammenstöpseln das ein komplett fertiges Model mit zwei verschiedenen fertigen Views verbindet und damit einen Vorteil von der Model/View-Trennung gegenüber Widgets die sowohl Anzeige als auch Datenhaltung vereinen zu zeigen. Die Dokumentation fängt an der Stelle halt noch einfacher an als Du das benötigst, aber sonst würden sich wieder andere beschweren das sie den Einstieg nicht finden oder nur über teure Bücher. :-)
Antworten