Seite 1 von 1
Tkinter Inhalte wieder löschen
Verfasst: Freitag 24. April 2020, 04:36
von Neu111
Hallo!
Folgende Ausgangslage:
Code: Alles auswählen
def showReihe2(event):
bu1 = Button(master, width=13, text='Schaltfläche 1', command=lambda:berechnung('variante1'))
bu1.grid(row=2, column=0, sticky=W, padx=1)
bu2 = Button(master, width=13, text='Schaltfläche 2', command=lambda:berechnung('variante2'))
bu2.grid(row=2, column=1, sticky=W, padx=1)
def loescheReihe2(event):
bu1.destroy()
bu2.destroy()
master.bind('g', showReihe2)
master.bind('b', loescheReihe2)
Drücke ich nun die Taste "g", so wird mir in der grafischen Oberfläche eine neue Zeile (row=2) mit den 2 Buttons eingeblendet.
Das funktioniert auch.
Nun möchte ich durch einen weiteren Tastaturbefehl (nochmaliger Tastendruck 'g' oder wie in meinem Beispiel die Taste 'b') die komplette Reihe 2 (row=2) wieder entfernen.
Dies funktioniert NICHT, weil in der zweiten Funktion "loescheReihe2" die Variable bu1 und bu2 nicht bekannt/definiert sind.
Wie kann ich das Problem lösen?
Re: Tkinter Inhalte wieder löschen
Verfasst: Freitag 24. April 2020, 06:37
von Sirius3
`bu1` und `bu2` sind lokale Variablen, die nur innerhalb von showReihe2 existieren. Ebenso sollte `master` eine lokale Variable sein, die als Argument showReihe2 übergeben wird.
Um das zu Ändern, muß man sich den Zustand (also die Knöpfe) über die Dauer des Funktionsaufrufst merken. Das macht man mit Klassendefinitionen. Jedes nicht-triviale GUI-Programm braucht das.
Benutze keine Abkürzungen, wenn Du schaltflaeche meinst, dann schreibe nicht bu. Besser wäre es noch, die Schaltfläche nach ihrer Bedeutung zu benennen. Funktionsnamen schreibt man wie Variablennamen klein_mit_unterstruch, also loesche_reihe2, eingerückt wird immer mit 4 Leerzeichen pro Ebene, keine Tabs und die Namen aus Tkinter werden üblicherweise per tk.Button angesprochen, mit dem entsprechenden Import `import tkinter as tk`.
Das Grundgerüst eines GUI-Programms sieht eigentlich immer ähnlich aus:
Code: Alles auswählen
import tkinter as tk
from functools import partial
class MasterWindow(tk.Tk):
def __init__(self):
super().__init__()
self.schaltflaeche1 = None
self.schaltflaeche2 = None
self.bind('g', self.show_reihe2)
self.bind('b', self.loesche_reihe2)
def show_reihe2(self, event):
if self.schaltflaeche1 is not None:
# Schaltflaechen schon erzeugt
return
self.schaltflaeche1 = tk.Button(master, width=13, text='Schaltfläche 1', command=partial(self.berechnung, 'variante1'))
self.schaltflaeche1.grid(row=2, column=0, sticky=tk.W, padx=1)
self.schaltflaeche2 = tk.Button(master, width=13, text='Schaltfläche 1', command=partial(self.berechnung, 'variante2'))
self.schaltflaeche2.grid(row=2, column=1, sticky=tk.W, padx=1)
def loesche_reihe2(self, event):
if self.schaltflaeche1 is None:
# keine Schaltflaeche da
return
self.schaltflaeche1.destroy()
self.schaltflaeche2.destroy()
self.schaltflaeche1 = None
self.schaltflaeche2 = None
def berechnung(self, variante):
pass
def main():
master = MasterWindow()
master.mainloop()
if __name__ == '__main__':
main()
Man versucht eigentlich, zu vermeiden, im nachhinein ein Fenster zu verändern. Üblich ist es, die Knöpfe schon in __init__ zu erzeugen und nur bei Bedarf anzuzeigen, bzw. aktiv zu schalten.
Re: Tkinter Inhalte wieder löschen
Verfasst: Freitag 24. April 2020, 21:44
von Neu111
Wow!
Mit so einer detaillierten Antwort hätte ich nicht gerechnet.
Vielen vielen DANK an Sirius3!!!!
Der Code funktioniert wunderbar, ich musste nur eine kleine Korrektur vornehmen (..tk.Button(master... durch tk.Button(self ... ersetzt)
Abschließend hätte ich noch ein paar Verständnisfragen:
1.) was ist der Unterschied zwischen
und
2.) was ist der Unterschied zwischen
und
3.) Wenn eine Funktion definiert wird, dann steht innerhalb der Runden Klammer zunächst ein "self":
Was bewirkt das "self" innerhalb dieser runden Klammer?
4) Warum keine Tabs beim einrücken?
...eingerückt wird immer mit 4 Leerzeichen pro Ebene, keine Tabs ...
5) Diese Zeile verstehe ich überhaupt nicht:
Kann mir die Codezeile jemand etwas ausführlicher erklären?
PS: noch einmal recht herzlichen Dank an Sirius3 für seinen letzten Post!
Re: Tkinter Inhalte wieder löschen
Verfasst: Samstag 25. April 2020, 14:58
von Sirius3
Mit ›from tkinter import *‹ wird jeder Name der im Modul auch in den eigenen Namensraum geladen. Du hast also keine Kontrolle darüber, welche Namen das sind und es könnten welche, die Du selbst definiert hast, überschrieben werden. Bei ›import tkinter as tk‹ hat man die klare Trennung und kann kontrolliert per tk.xyz auf die Namen zugreifen.
Mit `partial` erzeugt man eine Funktion mit vordefinierten Parametern, bei lambda wird eine anonyme Funktion ohne eigenen Namensraum definiert, was zu seltsamen Fehlern führen kann.
`self` ist ein ganz normales Argument der Methode, wird aber automatisch mit der Instanz, die die Methode aufruft, belegt.
Tabs sind je nach Editor-Einstellung unterschiedlich groß, der Quellcode sieht also je nachdem unterschiedlich aus. Bei Leerzeichen kann das nicht passieren.
__name__ ist eine automatisch definierte Variable, die den Namen des Moduls enthält. Bei Skripten enthält sie den Wert "__main__". Damit kann man Module schreiben, die sich anders verhalten, wenn sie Importiert werden, wie wenn sie als Skript gestartet werden. Damit lassen sich Skripte auch als Module verwenden, was unter anderem bei multiprocessing, automatischer Dokumentation oder Unit-Tests benutzt wird.
Re: Tkinter Inhalte wieder löschen
Verfasst: Montag 27. April 2020, 15:59
von Neu111
@Sirius3:
nochmal zu deinem Code oben:
Code: Alles auswählen
self.bind('g', self.show_reihe2)
self.bind('b', self.loesche_reihe2)
Gibt es eine Möglichkeit, die Aktion "self.show_reihe2" und "self.loesche_reihe2" mit ein- und derselben Taste auszuführen?
Sprich:
Taste g wird zum ersten Mal gedrückt --> "show_reihe2"
Taste g wird zum zweiten Mal gedrückt --> "loesche_reihe2"
Taste g wird zum dritten Mal gedrückt --> "show_reihe2"
usw.
Re: Tkinter Inhalte wieder löschen
Verfasst: Montag 27. April 2020, 16:39
von __deets__
Natuerlich, dann musst du dir nur merken, das du schonmal was gedrueckt hast, und entsprechend was anderes machen. Aber natuerlich in ein und derselben Rueckruffunktion.