QTableModel, Vererbung

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
raorao
User
Beiträge: 24
Registriert: Mittwoch 30. Dezember 2009, 15:35

Hallo Welt...

Folgendes Problem betrifft zwar eher das Thema mehrfache Vererbung, aber die verwendeten Klassen kommen aus PySide (bzw. PyQt4). MyTableModel steht exemplarisch für eine Subklasse von QSqlTableModel, die die Daten für die View aufbereiten soll. Da in einer verwendeten Tabelle nun aber foreign keys stehen, brauche ich dafür zusätzlich die Methoden von QSqlRelationalTableModel. Daher bietet es sich an, für die Subklasse MyRelationalTableModel von MyTableModel und von QSqlRelationalTableModel zu erben um die Funktionalität aus beiden Klassen zu haben.
Nun arbeitet MyTableModel wunderbar korrekt, aber MyRelationalTableModel kann rowCount nicht ausführen, obwohls im dir() gelistet ist und diese Methode eigentlich via MyTableModel - QSqlTableModel erben müsste...

Vielen Dank für die Aufklärung des Konfuzius...
raorao

Code: Alles auswählen

from PySide.QtSql import *

class MyTableModel(QSqlTableModel):
    
    def __init__(self, parent = None, db = QSqlDatabase()):
        super(MyTableModel, self).__init__(parent, db)
        
    def columnCount(self):
        return 3

class MyRelationalTableModel(MyTableModel, QSqlRelationalTableModel):
    
    def __init__(self, parent = None, db = QSqlDatabase()):
        super(MyRelationalTableModel, self).__init__(parent, db)

#model = MyTableModel()
model = MyRelationalTableModel()
print 'rowCount' in dir(model)
print model.rowCount()
print 'Ende'
BlackJack

@raorao: Kann nicht ausführen bedeutet was genau? Und Dir ist klar, das sowohl `QSqlTableModel` als auch `QSqlRelationalTableModel` eine `rowCount()`-Methode haben?
lunar

@raorao: Hast Du Dir eigentlich Gedanken über die Semantik dieser Vererbungshierarchie gemacht, die über „Funktionalität aus beiden Klassen haben“ hinausgehen? Anders gefragt, kannst Du erklären, wo beispielsweise ein Aufruf von "MyRelationalTableModel.data()" endet?

Im Allgemeinen ist Deine Vererbungshierarchie ein Diamant, da "QSqlTableModel" sowohl Basisklasse von "MyTableModel" als auch von "QSqlRelationalTableModel" ist. Diese Art der Vererbungshierarchie wird von Qt nicht unterstützt, da Qt keine virtuelle Vererbung nutzt. Zudem verwenden C++ und Python verschiedene Algorithmen zur Auflösung von Methodenaufrufen in solchen Hierarchien, insbesondere hat Qt logischerweise keine Ahnung davon, wie und in welcher Reihenfolge "super()" Methoden der Basis-Klasse aufruft. Der Versuch, alle Basiskonstruktoren mit "super()" aufzurufen, muss also notwendigerweise an der Grenze zu C++-Klassen scheitern, so dass bei dieser Hierarchie immer irgendwo uninitialisierte Objekte erzeugt werden, da eben nicht alle Basiskonstruktoren korrekt aufgerufen werden.

Lange Rede, kurzer Sinn: Du darfst nicht von zwei Qt-Klassen gleichzeitig ableiten, weder in C++ noch in Python. Und nein, ein Wechsel zu PyQt würde auch nicht helfen, PyQt erwähnt diese Einschränkung sogar explizit in der Dokumentation.
raorao
User
Beiträge: 24
Registriert: Mittwoch 30. Dezember 2009, 15:35

Vielen Dank für diese super Antwort! Mir war natürlich bewusst, dass es sich um einen Diamant handelt, aber Python kann solche normalerweise auflösen. Mir war hingegen nicht bewusst, dass Qt da an die Grenzen stösst, aber ist aufgrund der Basis in C++ eigentlich nur logisch... Wieder etwas gelernt! Herzlichen Dank! raorao
Antworten