Wie leitet man Class zu MainWindow richtig ab?

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
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammmen,

meine Class MainWindow:

Code: Alles auswählen

class MainWindow(QtGui.QMainWindow):
    count = 0
        
    def __init__(self):
        super(MainWindow, self).__init__()
Nun möchte ich eine weitere Class bauen, die auf self von MainWindow zugreift.
Ich habe dazu dies erstellt:

Code: Alles auswählen

class SubWindow(MainWindow):
        
    def __init__(self, parent):
        super(MainWindow, self).__init__(parent)
        self.parent = parent
Ich bin mir aber nicht letzendlich sicher, ob das so richtig ist, oder doch anderst umgesetzt werden muss.
Daher würde ich mich auf Euren Input freuen, um Fehler im Vorfeld zu vermeiden!

Grüße Nobuddy
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was hindert dich daran, die Instanz des mainwindow einfach als normales Argument an den konstruktor zu übergeben?
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Bin mir nicht sicher, ob Du das damit meinst:

Code: Alles auswählen

class MainWindow(QtGui.QMainWindow):
    count = 0
        
    def __init__(self):
        super(MainWindow, self).__init__()
        .....

    def closed_sublists_updateting(self):
        print('Mach etwas ....')
Ich möchte gewisse Funktionen aus MainWindow auslagern, um die Class MainWindow übersichtlicher zu haben. Ist das was Du mir geschrieben hasrt, identisch mit meinem Vorhaben?
Sirius3
User
Beiträge: 18269
Registriert: Sonntag 21. Oktober 2012, 17:20

@Nobuddy: bisher wird es nur unübersichtlicher. Was steht denn alles in MainWindow drin? Vielleicht sollte man da ansetzen und umstrukturieren, statt einfach eine Klasse per Vererbung in zwei aufzuteilen.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Ok, ich versuche es mal zusammenzufassen.
Meine MainWindow Class besitzt eine MenuBar, eine ToolBar horizontal unten, sowie eine Toolbar vertikal links und rechts.
Ich öffne Listen zu verschiedenen Bereichen. Die ToolBar rechts listet die Masterbereiche auf.
Beim Klicken auf einen Masterbereich, öffnet sich die linke ToolBar mit entsprechenden Listen zur Auswahl, bzw. Funktionen zur Bearbeitung. Die ToolBar links passt sich immer dem Masterbereich an der geklickt wurde. Funktionen, die den Aufgabenbereich verwalten, sind vorhanden.

Bei den Listen, kann durch Auswahl eines Datensatzes eine Ausgabe als Dataset in einem neuen Fenster erfolgen. Dieser Datensatz lässt sich dann bearbeiten, bzw. einen neuen Datensatz erstellen. Gleichermaßen erfolgt das Löschen eines Datensatzes durch entsprechende Auswahl. Das Listenfenster ist immer hinter dem Dataset-Fenster, das auf Normalgröße eingestellt ist.
Für die Kontrolle beim öffnen von Listen, bzw. offener Listen, bestehen Funktionen, die den Aufgabenbereich verwalten, sind vorhanden.

In der MenuBar habe ich mit unter, ein Menü das 'Offene Fenster' heißt. Dort werden alle geöffneten Listen und Datasets gelistet, die durch Auswahl als vorderstes Fenster dann erscheint.
Möchte ich eine Liste schließen, bei der ein zugehöriges Dataset noch offen ist, wird eine entsprechende Meldung ausgegeben. Auch hier ist das Listenfenster immer hinter dem Dataset-Fenster, das auf Normalgröße eingestellt ist. Funktionen, die den Aufgabenbereich verwalten, sind vorhanden.

Es gib noch weitere Funktionen, die dazu gehören, aber um die Übersicht nicht zu verlieren, belasse ich es mal dabei.

Weitere Klassen gehören dazu, die z.B. für Tabellen, MessageBox, MenuBar, ToolBar und weitere Tools.

Ich weiß jetzt nicht, wie ich das umstrukturieren soll, ohne eine große unübersichtliche Klasse am Ende zu haben. Wobei auch noch dazu gesagt, alles auf die MainWindow Klasse zugreift, bzw. Informationen erhält.
Benutzeravatar
__blackjack__
User
Beiträge: 14040
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Nobuddy: Die Beschreibung ist ja ganz nett, erklärt aber nicht warum Du jetzt bereits eine Klasse mit zu vielen Methoden hast. Und die in mehrere Klassen aufzuteilen die durch *Vererbung* dann doch wieder alles in ein „god object“ zusammen werfen ist keine Lösung. Das auf mehrere Klassen zu verteilen die dann per Komposition zusammengeführt werden, wäre vielleicht eine Lösung.
„A life is like a garden. Perfect moments can be had, but not preserved, except in memory. LLAP” — Leonard Nimoy's last tweet.
Benutzeravatar
sparrow
User
Beiträge: 4537
Registriert: Freitag 17. April 2009, 10:28

@Nobuddy: Warum kommen diese ganzen Objekte denn nicht in einen entsprechenden Pool (Modul) von wo du sie in die Klassen importierst, die du brauchst?
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

__blackjack__ hat geschrieben: Sonntag 27. Januar 2019, 21:01 @Nobuddy: .......... Das auf mehrere Klassen zu verteilen die dann per Komposition zusammengeführt werden, wäre vielleicht eine Lösung.
Das wäre vielleicht das was ich suche, nur wie würde das dann aussehen?
Vielleicht so:

Code: Alles auswählen

class SubWindow(object):
        
    def __init__(self, parent):
        self.parent = parent
Oder doch anderst?
sparrow hat geschrieben: Sonntag 27. Januar 2019, 23:22 @Nobuddy: Warum kommen diese ganzen Objekte denn nicht in einen entsprechenden Pool (Modul) von wo du sie in die Klassen importierst, die du brauchst?
Das ist nicht das Problem, das wäre dann das obige Beispiel, dann ein Modul zu importieren auch nicht.

Ich dachte, dass eine Vererbung sinnvoll wäre, was aber nach Eurem Rat nicht der Fall sein dürfte.
Wenn ich ein neues Projekt starte, möchte ich es diesmal von Anfang an richtig machen, daher auch mein jetziges Anliegen.
Sirius3
User
Beiträge: 18269
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast Klassen für Datasets, Tabellen, etc. Jede hat Methoden, die darauf operieren. Diese kombinierst Du so, wie Du die Funktionalität, die diese Klassen bieten, brauchst, also übergibst oder erzeugst Instanzen von diesen Klassen an andere Instanzen anderer Klassen.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

So langsam glaube ich zu verstehen, eine Klassenvererbung ist hier das Falsche.
Das Richtige, ist wohl dies:

Code: Alles auswählen

class SubWindow(object):
        
    def __init__(self, parent):
        self.parent = parent

    def closed_sublists_updateting(self):
        """
        List names to be deleted with associated datasets
        """

        closed_window = self.parent.mdi_area.activeSubWindow()
        ......
        ...
Als Beispiel meine Tabellen-Klasse:

Code: Alles auswählen

class Table(QtGui.QWidget):
    def __init__(self, mdi_area, title, dataList, header, columnWidths):
        QtGui.QWidget.__init__(self)
        self.mdi_area = mdi_area
        self.title = title
        self.setWindowTitle(self.title) 
        ....
        ..
Habe ich das richtig verstanden?
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Hmm, keine Rückmeldung ..... liege ich total falsch .... oder doch nicht!?!?
Sirius3
User
Beiträge: 18269
Registriert: Sonntag 21. Oktober 2012, 17:20

@Nobuddy: aus den wenigen Zeilen, kann ich nicht sagen, ob Du richtig liegst. Ein bißchen total falsch sieht nur die lange Verkettung `self.parent.mdi_area` aus.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Sirius3 hat geschrieben: Dienstag 29. Januar 2019, 20:02 @Nobuddy: aus den wenigen Zeilen, kann ich nicht sagen, ob Du richtig liegst. Ein bißchen total falsch sieht nur die lange Verkettung `self.parent.mdi_area` aus.
Das liegt daran, dass ich aus MainWindow, self an die Class Table übergebe.
In der Class Table wird daraus parent > self.parent und in der Beispiel-Funktion self.parent.mdi_area.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist schon klar. Nur sind solche Ketten ungluecklich. Man nennt das "Demeter's Law". Sowas sollte man vermeiden, weil man dadurch eine sehr starke Kopplung an die Struktur eines anderen Objektes erzeugt. Ein beliebtes Beispiel aus der OO ist das Kommando "sitz!" an eine Klasse "Tier". Wenn du das so implementierst

Code: Alles auswählen

def sitz(tier):
       tier.vorderbein_links.gerade()
       tier.vorderbein_rechts.gerade()
       tier.hinterbein_links.angewinkelt()
       tier.hinterbein_rechts.angewinkelt()
dann funktioniert das halt nur fuer Vierbeiner. Vielleicht hast du aber eine Haustarantel, und die soll auch hoeren koennen. Da musst du dann aber ploetzlich 8 Beine steuern, 4 davon ganz anders. Besser ist es also, das dem Tier selbst zu ueberlassen in diesem Fall (das Beispiel hat da seine Grenzen). Es geht nur darum zu illustrieren, warum das "reinfingern" in Objekthierarchien unschoen ist.

Darum soll man wenn moeglich solche Argumente *explizit* uebergeben, also mdi_area gleich als Argument an SubWindow, wenn da nichts anderen gebraucht wird.
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Das verstehe ich, hatte das auch zuerst so gemacht.
Aber nach dem ich auch eine Funktion in MainWindow darüber anspreche, habe ich parent verwendet.
Vielleicht etwas unglücklich, aber mir ist da nichts besseres eingefallen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dann kann man ggf. zwei Argumente uebergeben. Ob das nun wirklich sinnvoll ist, haengt von zu viel ab, als das man das so pauschal mit ja oder nein beantworten kann. Generell ist es eher ein Zeichen fuer schlechten Entwurf, wenn das so ist. Was in mainwindow sind denn die anderen Dinge, die du brauchst?
Nobuddy
User
Beiträge: 1019
Registriert: Montag 30. Januar 2012, 16:38

Ja, da hast Du Recht, werde das entflechten, damit so etwas nicht nötig wird.
Antworten