[PyQt4] QMainWindow und QTableView kombinieren

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Ich bin dabei, ein Programm zum Erstellen von Stundenplänen zu erstellen. Das Model/View-Konzept funktioniert, d.h. timetable.py lässt sich direkt aufrufen und zeigt dann (wie gewünscht) eine Tabelle an. Von dem Modul main_window.py aus möchte ich den View mit setCentralWidget einbinden, was aber scheitert, weil QTableView nicht von QWidget ableitet.

Wie kann ich mit einen View in QMainWindow als zentrales Widget einbinden?
lunar

derdon hat geschrieben:Von dem Modul main_window.py aus möchte ich den View mit setCentralWidget einbinden, was aber scheitert, weil QTableView nicht von QWidget ableitet.
Unsinn, QTableView leitet sehr wohl von QWidget ab. Du solltest erstmal deine Imports korrigieren ;)

Anstatt mit View von QTableView zu vererben, kannst du im Übrigen auch einfach ein QTableView-Exemplar erzeugen und dann von außen ".setModel()" aufrufen. Man muss die Sache ja nicht unnötig verkomplizieren ;) Und die Modell-Klasse sollte vielleicht einen aussagekräftigeren Namen erhalten ;)
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

main_window.py, timetable.py und ein Scrrenshot

Wenn ich time.py direkt aufrufe, dann wird der TableView wie erwartet angezeigt (rechtes Fenster im Screenshot). Beim Aufrufen von main_window.py allerdings wird nur ein leeres Widget bzw. ein weißer weißer Bereich angezeigt (linkes Fenster im Screenshot).

Lunar: Was muss ich an meinen Imports korrigieren?
lunar

Höchst interessant. Ich kann das Verhalten reproduzieren, bin aber ehrlich gesagt ratlos, was dessen Ursache angeht. Ich hatte dieses "Phänomen" noch nie ;) Sorry.
derdon hat geschrieben:Lunar: Was muss ich an meinen Imports korrigieren?
In der ersten Version hast du "View" definiert, aber "ViewWidget" importiert ;)
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Problem ist gelöst (dank Hilfe aus #qt):
jpnurmi hat geschrieben:try self.model = ... and self.view = ...
well, at least for the model
apparently qmainwindow keeps a reference to the view so it remains alive, but nothing keeps a reference to the model currently so it gets automatically nuked
Die Dateien sehen jetzt so aus: main_window.py und timetable.py
lunar

Klar, logisch, daran hätte ich denken müssen.

Qt verwaltet Referenzen normalerweise in einem Objektbaum, so dass man sich nicht selbst darum kümmern muss. In deinem Code aber setzt du die Vater-Kind-Beziehungen nicht richtig. Beim View macht das nichts aus, weil QMainWindow beim Aufruf von .setCentralWidget() automatisch die Vaterschaft des View-Widgets übernimmt und somit eine Referenz hält.

Der View aber übernimmt die Vaterschaft zugewiesener Models nicht automatisch, da ein Model gleichzeitig mehrere Views haben kann. Daher musst du dem Model selbstständig ein Vaterobjekt zuweisen, in dem du den Code wie folgt änderst.

TimeTable.__init__():

Code: Alles auswählen

def __init__(self, filename, parent=None):
    QtCore.QAbstractTableModel.__init__(self, parent)
    # restlicher code
Btw, wenn du von QAbstractTableModel ableitest, solltest du auch dessen Konstruktor aufrufen ;)

Erzeugung des Models und des views:

Code: Alles auswählen

view = QTableView(self)
model = TimeTable(filename, view)
view.setModel(model)
self.setCentralWidget(view)
Dann funktioniert das Fenster auch ohne das Setzen eines Instanzattributs.

Memo für die Zukunft: Den Parameter "parent" im Konstruktor der ganzen Qt-Klassen sollte man auch nutzen ;)
Antworten