@bmbl: Du kannst da auch auf diese Weise keine eigene "main loop" haben. Das Programm hat ja schon eine, nämlich die Hauptschleife von `Tkinter`. Die ruft Deinen Quelltext bei bestimmten Ereignissen auf und da kannst Du dann kurz etwas machen. Solange Dein Code läuft, ist die GUI blockiert, dass heisst das sollte nicht lange dauern, was Du da machst. So ein linearer Programmablauf wie bei der Kommunikation mit dem Anwender auf der Textkonsole mit Schleifen oder gar `sleep()` für Wartezeiten, funktioniert bei ereignisbasierter GUI-Programmierung nicht mehr. Die `update()`-Methode musst Du nur aufrufen, weil Du die GUI-Hauptschleife nicht ihren Job erledigen lässt.
Die Namensgebung ist übrigens ziemlich schlecht. Was soll das `f_` vor den Methoden? Warum die Abkürzungen und Durchnummerierung von Namen? Bei dem hier weiss doch kein Mensch was da eigentlich passiert, ohne zu suchen was `btn1` bis `btn3` bedeutet:
Code: Alles auswählen
self.status = True
self.btn1.configure(state=DISABLED)
self.btn2.configure(state=NORMAL)
self.btn3.configure(state=DISABLED)
So wäre das viel verständlicher, ohne das man die Zuweisung an die Attribute suchen müsste:
Code: Alles auswählen
self.running = True
self.start_button.configure(state=DISABLED)
self.stop_button.configure(state=NORMAL)
self.load_button.configure(state=DISABLED)
Warum stecken die Vokabeln in einem Dictionary, das Zahlen von 0 bis Anzahl der Vokabeln minus 1 auf Paare von Zeichenketten abbildet? Das klingt viel eher nach einer Liste. Dann könnte man auch `random.choice()` verwenden um ein Paar auszuwählen.
Ein Objekt sollte in der `__init__()` möglichst komplett initialisiert werden, so dass dort alle Attribute mit sinnvollen Werten vorbelegt werden. Wenn man in anderen Methoden neue Attribute einführt, werden Programme schnell unübersichtlich.
Das Laden ist ziemlich umständlich. Neben der schon erwähnten Liste für die Daten, kann man über die Zeilen einer Datei mit ``for`` iterieren. Und Du erfindest das Rad neu, beziehungsweise die `split()`-Methode auf Zeichenketten. Mit einer "list comprehension" schrumpft die Methdode auf das hier zusammen:
Code: Alles auswählen
def laden(self):
lines = open(tkFileDialog.askopenfilename(initialdir='',
filetypes=[('Text',
'*.txt')]))
self.vocab = [line.strip().split('#', 1) for line in lines]
lines.close()
self.start_button.configure(state=NORMAL)