OOP Fragen, tkinter ,multi window

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
Benutzeravatar
Blackshie
User
Beiträge: 13
Registriert: Mittwoch 17. Januar 2018, 15:45

Hallo,
nun versuche ich einen anfang in die Objektorientierte Programmierung zu finden.
So ganz erschließt sich mir zwar das Konzept, die sinnvolle Verwendung dessen aber noch nicht ganz.

Ich habe mehre Fenster in tkinter, sowie muss ich Benutzereingaben verarbeiten und Berechnungen ausführen.

Bisher hatte ich das funktional gelöst, doch dachte ich mir ich schreibe es OOP. Soll ja übersichtlicher und leichter zu warten sein hört man immer.

konkret heißt das ich schreibe für jedes Fenster eine eigene Klasse.
ich habe eine (Klasse children window) von der das erste Fenster gezeichnet wird. Von dort aus mochte ich zum Fenster (main window) in der dann die Berechnungen stattfinden, und natürlich wieder zurück. Diese Berechnungen (Klasse Algo) finden dann in einer ganz anderen Klasse statt, die so erstmal nichts mit den Fenstern zu tun hat.
Ich habe dabei alle Attribute die ich nur intern brauche mit einem unterstrich begonnen. Ebenso bei den Methoden.

Nun es funktioniert soweit alles.
nur meine Frage an euch ist jetzt ob ich das ganze jetzt korrekt und vor allem sinnvoll benutzt habe.

Ich stelle hier ein kleines Stück Code rein (vereinfacht nur als Beispiel), um vielleicht zu zeigen wie ich es mein.

Code: Alles auswählen

import tkinter as tk

class Algo():
    
    # Hier sind viele Methoden zum berechnen
    # Die klasse hat nichts mit den Fenster Klassen zu tun
    #
    #
    # beispiel
    def add(self, String):
        tmp = main()
        String += tmp.Dateiname
        return String


class main():
    
    def __init__(self):
        # Attribute die auch von aussen verfügbar sein müssen
        self.Dateiname = "Testdatei.dat"
    
    def create(self):
        self._main = tk.Tk()
        
        buttonback = tk.Button(self._main, text="back", command=self._back)
        buttonback.pack()
        
        # Buttons die auf Methoden der aktuellen Klasse zugreifen
        button2 = tk.Button(self._main, text="add", command=self._go)
        button2.pack()
        
        self._label = tk.Label(self._main, text="TestLabel|")
        self._label.pack()

        self._main.mainloop()
        
    def _go(self):
        # hier wird die Algorithmus Klasse aufgerufen sowie Bedingungen geprüft
        # hier werden auch die Elemte des Fensters manipuliert
        A1 = Algo()
        self._label["text"] = A1.add(self._label.cget("text"))
        
    def _back(self):
        self.destroy()
        child_window = window()
        child_window.create()
        
    def destroy(self):
        self._main.destroy()


class window():
    
    def create(self):
        self._main = tk.Tk()
        
        tk.Label(self._main, text="test1").pack()
        tk.Label(self._main, text="test2").pack()
        tk.Label(self._main, text="test3").pack()
        
        button = tk.Button(self._main, text="weiter", command=self._weiter)
        button.pack()
        
        self._main.mainloop()
        
    def destroy(self):
        self._main.destroy()
        
    def _weiter(self):
        self.destroy()
        main_window = main()
        main_window.create()


new = window()
new.create()

__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du solltest mal PEP8 anschauen, um dich mit den Namenskonventionen fuer Python vertraut zu mache. Klassen werden mit Grossbuchstaben am Anfang geschrieben, so wie du das mit Algo machst, aber *NICHT* mit main. Was der Name einen Funktion waere, da klein geschrieben.

Was du definitiv nicht richtig machst ist eine create-Methode einzufuehren. Dazu ist die Initialisierungs-Methode __init__ gedacht.

Die Rekursion in der Klasse main, die sich selbst wieder instantiiert, ist auch auesserst seltsam.

Last but not least: gerade weil deine Klasse Algo nix mit der GUI zu tun hat, ist es genau falsch, darin eine GUI-Klasse zu erzeugen. Das vorgehen ist ueblicherweise andersherum. Der Algorithmus legt ja los zB auf Tastendruck.

Also zumindest fuer diesen Ausschnitt ist deine Frage, ob du das sinnvoll nutzt, leider mit nein zu beantworten. Ist aber nicht schlimm, kein Meister ist vom Himmel gefallen.
Benutzeravatar
Blackshie
User
Beiträge: 13
Registriert: Mittwoch 17. Januar 2018, 15:45

Du solltest mal PEP8 anschauen, um dich mit den Namenskonventionen fuer Python vertraut zu mache.
Werde ich machen
Was du definitiv nicht richtig machst ist eine create-Methode einzufuehren. Dazu ist die Initialisierungs-Methode __init__ gedacht.
Danke, das ist mir auch noch eingefallen.
Also zumindest fuer diesen Ausschnitt ist deine Frage, ob du das sinnvoll nutzt, leider mit nein zu beantworten. Ist aber nicht schlimm, kein Meister ist vom Himmel gefallen.
Der Auschnitt ist natürlich nur ein Beispiel, aber ich fände es super wenn du mir noch weitere Punkte nennst, welche ungewöhnlich oder falsch in meinem Gedankengang sind.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Fuer das was du gezeigt hast, war's das so ziemlich. Wobei ich gerade gesehen habe, das du Algo aufrufst in main - du hast da also ein munteres Ping-Pong. Das kann so nicht gedacht sein. Wahrscheinlich willst du eher Algo aufrufen in main, und dabei *self* als Argument uebergeben, damit sich Algo wiederum an den Eigenschaften von main bedienen kann. Wobei das nicht so besonders gut ist: du solltest zB sowas wie den Dateinamen einfach direkt als Argument an Algo uebergeben, statt einen Sack mit Daten. Denn dann kann man Algo nur mit genau dem Sack aufrufen, bzw. einem, der zumindest sehr, sehr aenhlich aussieht. Und das ist eher ungeschickt.
Sirius3
User
Beiträge: 17739
Registriert: Sonntag 21. Oktober 2012, 17:20

@Blackshie: GUI und OOP am Anfang zu mischen, ist schwierig, weil GUIs einige Besonderheiten haben, die von der reinen OOP-Lehre abweichen.

Rein Funktional ist übersichtlicher und leichter zu warten, weil es keine Zustände gibt und damit die Korrektheit eines Algorithmus leichter zu prüfen ist. Was Du wahrscheinlich meintest war »prozedural« was ganz ähnlich zu »objektorientiert« ist und generell ist das eine nicht besser als das andere, sondern je nach Fall anzuwenden.

Womit wir schon bei »Algo« wären. Das ist keine Klasse, weil sie kein Objekt kapselt. Viele Methoden ist kein Grund, eine Klasse zu schreiben. »add« ist nichteinmal ein richtige Funktion, weil ein main-Objekt erzeugt wird, das dort überraschend auftaucht.

Eine Klasse ist dann sinnvoll, wenn es gilt, einen Zustand mehreren Methoden, die inhaltlich zusammengehören, zur Verfügung zu stellen, also ein Formularfenster, mit mehreren Eingabefeldern. Klassen werden in der Methode »__init__« initialisiert und sind danach vollständig funktionsfähig. Das bedeutet, alle Attribute haben einen Startwert. Das trifft schon eher auf Deine »create«-Methoden zu, die aber nicht erzeugen, sondern viel mehr (und damit zu viel) machen.

Nun zu Tkinter. Dort darf es eigentlich nur ein Tk-Exemplar geben; man hat also ein Hauptfenster, von dem aus man noch beliebig viele TopLevel-Exemplare als Nebenfenster erzeugen darf. Dass das eine Fenster zerstört und das andere Erzeugt wird und wie bei Pingpong immer hin und her geht, ist sehr ungewöhnlich, der Programmierer würde sagen, ein Designfehler.
Benutzeravatar
Blackshie
User
Beiträge: 13
Registriert: Mittwoch 17. Januar 2018, 15:45

@Sirius3

Danke für die Erklärung.
Eine Klasse ist dann sinnvoll, wenn es gilt, einen Zustand mehreren Methoden, die inhaltlich zusammengehören,zur Verfügung zu stellen[...]
Nun zu Tkinter. Dort darf es eigentlich nur ein Tk-Exemplar geben; man hat also ein Hauptfenster, von dem aus man noch beliebig viele TopLevel-Exemplare als Nebenfenster erzeugen darf.
werde ich mir anschauen
Antworten