Seite 1 von 1

Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 15:42
von Midori
Hallo liebes Forum. Nachdem ich mich vor einiger Zeit dazu entschloßen hatte endlich das nachzuholen, was ich schon vor 15 Jahren hätte tun sollen. Und zwar das Programmieren lernen. So seh ich derzeit teilweise den Wald vor leute Bäumen nicht und es fällt mir schwerer als ich es gedacht hätte. Hut ab an alle die das Coden richtig beherrschen.

Nun zu meinem Problem. Ich habe Anfangs aufgrund eines Buches ein wenig mit Pygame gebastelt. Allerdings bin ich dann schnell rüber zu Tkinter um erstmal die Basics zu beherrschon und Spiele waren eh nicht mein Ziel. Und hier tue ich mir gerade noch ein wenig schwer wenn man von Tkinter eine Objekt Klasse erzeugen möchte und wie man das richtig richtig anstellt damit das sauber ist.

Bisher hatte ich das meist nur prozedural?! gestrickt und das lief soweit auch ganz gut. Aber wenn ich das richtig verstehe und der Code sauber sein soll, dann sollte ich das mit OOP angehen und alle programme die ich schreibe imprinzip über if __main__ == '__name__': laufen lassen damit man klassen z.b. später auch importieren kann und der code obendrein sauber zu lesen ist, wenn ich das richtig verstehe. Allerdings bin ich mir noch nicht ganz sicher wie ich dann die Klassen untereinander anspreche, wo die Tkinter Elemente hingehören und wo nicht.

Ich habe jetzt mal den Thread Tkinter Zeichenfeld als Anlass genommen und versucht eine rudimentäre Lösung zu stricken, nur bin mir z.B unsicher ob Bind z.B in der richtigen Funktion liegt. Irgendwie habe ich dir befürchtung das ich da noch etwas ziemlich falsch angehe, kann aber nicht sagen was. Wäre klasse wenn dort mal jemand drüberschauen könnte und mir das auseinandernimmt. :twisted:

Und über einen Link zu einem überschaubarem Beispiel Programm mit Tkinter und was vorbildlich aufzeigt wie das auszusehen hat würde ich mich ebenfalls freuen.

Code: Alles auswählen

import Tkinter as tk

class MainWindow():
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.frame.pack()
        self.master.title("GUI")
        self.master.geometry("600x600")

        self.canvas = tk.Canvas(self.frame, width=600, height=600, bg="white")
        self.canvas.pack(side="top",expand=True, fill="both")
        
    def draw(self,event):
        x1, y1 = (event.x - 1),(event.y - 1 )
        x2, y2 = (event.x + 1),(event.y + 1)
        self.canvas.create_oval(x1,y1,x2,y2, fill="black")
           
           
def main():
    root = tk.Tk()
    app = MainWindow(root)
    app.canvas.bind("<B1-Motion>", app.draw)
    root.mainloop()
    

if __name__ == '__main__':
    main()           

Re: Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 16:00
von BlackJack
@Midori: Ich würde das `bind()` mit in die `__init__()` packen. Ohne das ist das `MainWindow`-Objekt in diesem Fall nicht sinnvoll nutzbar und ich sehe bei dem Beispiel auch keinen Grund warum das Programm ausserhalb der Klasse diese Verbindung kennen muss.

Ich hätte `MainWindow` wahrscheinlich mindestens von `Frame` abgeleitet, bei dem Namen vielleicht sogar von `Tk`, denn *das* ist ja das Hauptfenster in einem Tk-Programm.

Re: Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 18:29
von __deets__
BlackJack hat geschrieben: Ich hätte `MainWindow` wahrscheinlich mindestens von `Frame` abgeleitet, bei dem Namen vielleicht sogar von `Tk`, denn *das* ist ja das Hauptfenster in einem Tk-Programm.
Ich halte dagegen: https://en.wikipedia.org/wiki/Compositi ... nheritance - Composition over inheritance.

Re: Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 18:37
von Sirius3
@__deets__: MainWindow ist ein Hauptfenster, oder zumindest ein Frame. Ich sehe hier jetzt keine Komposition.

Re: Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 19:44
von BlackJack
@__deets__: Was Sirius3 sagt und ich habe ja extra „bei dem Namen“ dazu geschrieben. Alternativ könnte man die Klasse auch in `DrawingApp` oder so umbenennen, aber wenn das Ding Hauptfenster heisst, könnte es auch eines *sein*. „ist-ein(e)“ ist ja genau der Beziehungstyp für Vererbung.

Re: Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 21:45
von __deets__
MainWindow ist die Klasse, die ein Mainwindow, ggf. mit zusaetzlichem Brimborium, erzeugt und verwaltet. Da sie ihrerseits nicht in einer Widgethierarchie verwandt wird, bei der Vererbung gefordert sein mag, oder man sonst eh alles an Verhalten weiterleiten/nachbilden soll, wuerde ich das auch nicht machen. So wie es zB Qt mit seinen .ui-Dateien auch vorgibt.

Klar kann man das auch noch mal umbenennen in *App in diesem Fall, aber fuer zB einen komplexen Dialog etc. wuerde ich eine solche Klasse trotzdem noch MeinTollerDialog nennen, aber immer noch nicht ableiten.

Und die Gruende sind in meinen Augen hoehere Flexibilitaet. Im Zweifel bekommt die Klasse das Container-Widget als Abhaengigkeit reingereicht, statt sie selbst zu erzeugen, und so wird aus einem frei stehenden Dialog ein Tab innerhalb einer Liste. Wo seht ihr den Vorteil der Vererbung?

Re: Tkinter als Klasse - Musterbeispiel

Verfasst: Dienstag 21. März 2017, 22:01
von BlackJack
@__deets__: Das ist semantisch eben ein Fenster oder zumindest ein Widget. Und zumindest wenn man das Hauptfenster nennt ist es komisch wenn es dann keines *ist*. Qt und *.ui-Dateien können hier IMHO nicht als Begründung herangezogen werden weil das hier nicht Qt ist und die Dinge anders gehandhabt werden.

Die Flexibilität von Komposition wird hier nicht benötigt, also KISS. Man spart sich beim Ableiten von `tk.Frame` den extra `Frame` und hat trotzdem noch die Freiheit das Containerwidget rein zu reichen.