Home
Navigation
Impressum
Coder Welten - Programmierung und Optimierung
Coder Welten
 
 

 

 

Tkinter: Code-Varianten für ein Countdown Script

Vorstellung der Tkinter after-Methode

Tkinter bietet als Basis für alle Widgets eine Vielzahl von Methoden, zu denen unter anderem die after-Methode gehört. Mit der after-Methode ist es möglich, eine bestehende Funktion oder Methode rekursiv aufzurufen, nur dass die Funktion sich nicht selbst aufruft, sondern die after-Methode diese Aufgabe übernimmt. Eine Verwendung der after-Methode hat je nach Anwendung den programm­technischen Vorteil, dass die Aufrufe nicht in schneller Folge abge­arbeitet werden, sondert entsprechend einer in Millisekunden anzugebenen Ver­zögerungszeit.

Das erste Beispiel soll nur den Ablauf verdeutlichen, obwohl durchaus lauffähig. In diesem Beispiel würde bei Aufruf der Funktion mit dem Parameter der Wert 0 an die Funktion übergeben. Parameter dienen der Übergabe, innerhalb des Kopfes einer Funktion oder einer Methode werden die Parameterwerte an Argu­mente über­geben, da sich mit Argumenten besser argumentieren lässt. Im Beispiel beginnt die Argumentation bei 0 und steigert sich bei jedem rekursiven Aufruf um +1.
Damit die Funktion nicht bis in alle Ewigkeit läuft bzw. nicht ewig rekursiv durch die after-Methode erneut aufgerufen wird, erfolgt nach 19 +1 = 20 kein erneuter Aufruf. Bis 20 wird jedoch bei Aufruf der Funktion der jeweils aktuelle Wert ins Label-Widget geschrieben. Die Verzögerungszeit ist im Beispiel auf 100 Millise­kun­den eingestellt und so würde in der Ausgabe innerhalb von 2 Sekunden von 1 bis 20 hochgezählt.

Erwähnt sei nebenher, die Zeile mit "argument = argument +1" könnte entfallen, wenn die +1 hinter dem Argument in der after-Methode notiert wird. In den anderen beiden Beispielen erfolgte die Notation dem Erwähnten entsprechend, wo­bei sich das Vorzeichen bei einem Countdown von plus nach minus ändert. Ebenso verändert sich bei einem Countdown der Anfangswert, da von einer höhe­ren Zahl herab statt herauf gezählt werden soll.

Beispiel Counter:

from tkinter import Tk, Label

def starte_counter(argument):
    # Bedingung erfüllt bis 19 plus 1
    if argument < 20:
        argument = argument +1
        # Rekursiver Aufruf, Verzögerungszeit in Millisekunden
        fenster.after(100, starte_counter, argument)
    # Schreibt bei jedem Aufruf den veränderten Wert ins Widget.    
    ausgabe["text"] = argument

fenster = Tk()
fenster.title("Counter")
ausgabe = Label(fenster)
ausgabe.pack()

# Funktionsaufrufe
starte_counter(0)
fenster.mainloop()

Ausgabe Counter
Laufende Ausgabe des Counters von 1 bis 20

Kommt das erste Beispiel noch unscheinbar daher, soll das folgende Beispiel hin­gegen den minimalen Anforderungen, die ein Programmierer an ein Count­down Script stellt, gerecht werden und etwas mehr einer Anwendung mit einer gra­fischen Benutzeroberfläche entsprechen. Da beide Varianten das gleiche Er­gebnis als Aus­gabe liefern, sollten zwei Screenshots genügen.

Srcript Countdown Start
Ansicht des Widgets beim Start und zur Laufzeit des Countdowns.

Ist der Countdown abgelaufen, ändert sich der eingeblendete Text und die Schrift graut aus.

Srcript Countdown Ende
Ansicht des Widgets am Ende des Countdowns.

Nachfolgend beide Code-Listings, wobei das erste Beispiel etwas einfacher im pro­ze­duralen Stil gehalten ist, das zweite Listing hingegen im objektorientierten Stil.

Code des ersten Tkinter Countdown-Scripts:

from tkinter import Tk, Label

def starte_countdown(count):
    counter["text"] = count
    # Rekursiver Aufruf der Funktion bis count 0 erreicht ist.
    if count > 0:
        # Zeit für rekursive Aufrufe in Millisekunden angeben.
        fenster.after(1000, starte_countdown, count -1)
    elif count == 0:
        fentext["text"] = "Countdown Ende"
        fentext["fg"]   = "#808080"

fenster = Tk()
fenster.title("Countdown")
fenster.wm_iconbitmap("neuronen.ico")
fenster.geometry("360x120")
fenster["bg"] = "#d9cda3"

fentext = Label(fenster,
                  text = "Countdown",
                    fg = "#904b00",
                  font = ("cambria", 12, "bold"),
                  pady = 12,
                    bg = "#d9cda3")

counter = Label(fenster,
                    fg = "#40ff40",
                  font = ("cambria", 20, "bold"),
                relief = "sunken",
                 width = 3,
                  pady = 4,
                    bd = 4,
                    bg = "#000")

fentext.pack()
counter.pack()

# Funktionsaufrufe
starte_countdown(10)
fenster.mainloop()

Doch nicht nur im Programmierstil unterscheiden sich beide Beispiele. So wird unter anderen im folgenden Script die configure-Methode (config) für durch die Funktion "starte_countdown" gesteuerten Änderungen von Text und Farbe genutzt und für die Ziffern die Klasse StringVar mit der Option "textvariable". Ändert sich der Wert von der Option "textvariable", so wird der Text des Labels aktualisiert.

Code des zweiten Countdown-Scripts im objektorientierten Stil:

from tkinter import Tk, Label, StringVar

class CountDown:
    """Eine Klasse für Widgets mit Countdown"""

    def __init__(self):
        self.fenster = Tk()
        self.fenster.title("Countdown")
        self.fenster.wm_iconbitmap("neuronen.ico")
        self.fenster.geometry("360x120")
        self.fenster.config(background = "#d9cda3")
        self.zaehler = StringVar()

        self.fentext = Label(self.fenster,
                          text = "Countdown",
                            fg = "#904b00",
                          font = ("cambria", 12, "bold"),
                          pady = 12,
                            bg = "#d9cda3")

        self.counter = Label(self.fenster,
                  textvariable = self.zaehler,
                            fg = "#40ff40",
                          font = ("cambria", 20, "bold"),
                        relief = "sunken",
                         width = 3,
                          pady = 4,
                            bd = 4,
                            bg = "#000")

        self.fentext.pack()
        self.counter.pack()

    def starte_countdown(self, count):
        self.counter = self.zaehler.set(count)
        if count > 0:
            self.fenster.after(1000, self.starte_countdown, count -1)
        elif count == 0:
            self.fentext.config(text = "Countdown Ende", fg = "#808080")

# --- Instanziieren eines Objektes der Klasse CountDown ---------------

if __name__ == "__main__":
    instanz = CountDown()
    instanz.starte_countdown(10)        # Countdown in Sekunden angeben
    instanz.fenster.mainloop()

Zur Instanziierung sei abschließend noch erwähnt, dass die Bedingung des State­ments "__name__ == __main__" nur zutrifft, wenn dieses Script mit der Klasse als eigenes Fenster aufgerufen wird.

 

Copyright © Verlag Horst Müller - Stendal - 2006 - Impressum - Datenschutz - Nutzungsbedingungen