i

Behandlung von Ereignissen

Zugriff auf Attribute von Ereignissen

Bei der Behandlung von Ereignissen kann man auf Attribute eines Ereignisses zugreifen. Dies wurde bereits im Programm des letzten Abschnitts ausgenutzt.

# Ereignisbehandlung

def plazieren(event):
    (x, y) = (event.x, event.y)
    (x0, y0, x1, y1) = tuple(canvas.coords(id_kreis))
    canvas.coords(id_kreis, (x, y, x+(x1-x0), y+(y1-y0)))

def entfernen(event):
    (x, y) = (event.x, event.y)
    (x0, y0, x1, y1) = tuple(canvas.coords(id_kreis))
    if x0 <= x and x <= x1 and y0 <= y and y <= y1:
        canvas.delete(id_kreis)

# Erzeugung der Komponenten

from tkinter import *
tkFenster = Tk()
tkFenster.title('Demo - Ereignisse')
tkFenster.geometry('400x300')
# Leinwand zum Zeichnen
canvas = Canvas(master=tkFenster, background='white')
canvas.place(x=10, y=10, width=380, height=280)
# Grafikobjekte
id_kreis = canvas.create_oval(100, 100, 120, 120, fill='red')
# Ereignisse
canvas.bind('<Button-1>', plazieren)
canvas.bind('<Button-3>', entfernen)

# Aktivierung der Ereignisschleife
tkFenster.mainloop()

Mit event.x bzw. event.y kann man die Koordinaten des Mauszeigers (bezogen auf die linke obere Ecke der angeklickten GUI-Komponente) zugreifen.

Weitere Zugriffsmöglichkeiten zeigt die folgende Übersicht.

Attribut Bedeutung
x, y Koordinaten des Mauszeigers (bezogen auf die linke obere Ecke der angeklickten GUI-Komponente)
char Zeichen bei einem Tastatur-Ereignis
num Nummer der gedrückten Taste bei einem Mausklick-Ereignis
widget Referenz auf die GUI-Komponente, durch die das Ereignis ausgelöst wurde
time Zeitwert in Millisekunden zur Bestimmung der Zeitspanne zwischen zwei Ereignissen

Anwendung - Vermeidung von Codepuplizierung

Im Abschnitt Der place-Manager wurde ein einfacher Rechner mit grafischer Benutzeroberfläche vorgestellt

Anwendungsfenster

Hier ein Auszug aus dem Quelltext. Den vollständigen Quelltext kannst du hier herunterladen.

from tkinter import *

def buttonPlusClick():
    # Übernahme der Daten
    zahl1 = int(entryZahl1.get())
    zahl2 = int(entryZahl2.get())
    # Verarbeitung der Daten
    ergebnis = zahl1 + zahl2
    # Anzeige der Daten
    labelErgebnis.config(text=str(ergebnis))

def buttonMinusClick():
    # Übernahme der Daten
    zahl1 = int(entryZahl1.get())
    zahl2 = int(entryZahl2.get())
    # Verarbeitung der Daten
    ergebnis = zahl1 - zahl2
    # Anzeige der Daten
    labelErgebnis.config(text=str(ergebnis))

def buttonMalClick():
    # Übernahme der Daten
    zahl1 = int(entryZahl1.get())
    zahl2 = int(entryZahl2.get())
    # Verarbeitung der Daten
    ergebnis = zahl1 * zahl2
    # Anzeige der Daten
    labelErgebnis.config(text=str(ergebnis))

def buttonDurchClick():
    # Übernahme der Daten
    zahl1 = int(entryZahl1.get())
    zahl2 = int(entryZahl2.get())
    # Verarbeitung der Daten
    ergebnis = zahl1 // zahl2
    # Anzeige der Daten
    labelErgebnis.config(text=str(ergebnis))

def buttonRestClick():
    # Übernahme der Daten
    zahl1 = int(entryZahl1.get())
    zahl2 = int(entryZahl2.get())
    # Verarbeitung der Daten
    ergebnis = zahl1 % zahl2
    # Anzeige der Daten
    labelErgebnis.config(text=str(ergebnis))

# Fenster
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
# Rahmen
...
# Button zum Addieren
buttonPlus = Button(master=frameBerechnen, text='+', width='2', command=buttonPlusClick)
buttonPlus.place(x=5, y=5, width=30, height=30)
# Button zum Subtrahieren
buttonMinus = Button(master=frameBerechnen, text='-', width='2', command=buttonMinusClick)
buttonMinus.place(x=45, y=5, width=30, height=30)
# Button zum Multiplizieren
buttonMal = Button(master=frameBerechnen, text='*', width='2', command=buttonMalClick)
buttonMal.place(x=85, y=5, width=30, height=30)
# Button zum Dividieren ohne Rest
buttonDurch = Button(master=frameBerechnen, text=':', width='2', command=buttonDurchClick)
buttonDurch.place(x=125, y=5, width=30, height=30)
# Button zum Rest bei der Division
buttonRest = Button(master=frameBerechnen, text='%', width='2', command=buttonRestClick)
buttonRest.place(x=165, y=5, width=30, height=30)
...
# Aktivierung des Fensters
tkFenster.mainloop()

Es fällt auf, dass die Ereignisbehandlungsprozeduren völlig analog aufgebaut sind und dass folglich Programmcode in ähnlicher Form mehrfach auftritt. Man spricht in einem solchen Fall von Codeduplizierung. Codeduplizierung lässt sich in der Regel vermeiden. Wie das im vorliegenden Fall möglich ist, zeigt das folgende Programm.

from tkinter import *

def rechnen(event):
    # Übernahme der Daten
    zahl1 = int(entryZahl1.get())
    zahl2 = int(entryZahl2.get())
    rechenzeichen = event.widget.cget('text')
    # Verarbeitung der Daten
    if rechenzeichen == '+':
        ergebnis = zahl1 + zahl2
    elif rechenzeichen == '-':
        ergebnis = zahl1 - zahl2
    elif rechenzeichen == '*':
        ergebnis = zahl1 * zahl2
    elif rechenzeichen == ':':
        ergebnis = zahl1 // zahl2
    elif rechenzeichen == '%':
        ergebnis = zahl1 % zahl2
    # Anzeige der Daten
    labelErgebnis.config(text=str(ergebnis))

# Fenster
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
# Rahmen
frameZahl1 = Frame(master=tkFenster, bg='#FFCFC9')
frameZahl1.place(x=5, y=5, width=80, height=60)
frameZahl2 = Frame(master=tkFenster, bg='#FFCFC9')
frameZahl2.place(x=115, y=5, width=80, height=60)
frameBerechnen = Frame(master=tkFenster, bg='#FBD975')
frameBerechnen.place(x=0, y=70, width=200, height=40)
frameErgebnis = Frame(master=tkFenster, bg='#D5E88F')
frameErgebnis.place(x=60, y=115, width=80, height=60)
# Label mit Aufschrift Zahl 1
labelZahl1 = Label(master=frameZahl1, bg='white', text='Zahl 1')
labelZahl1.place(x=5, y=5, width=70, height=20)
# Entry für Zahl 1
entryZahl1 = Entry(master=frameZahl1, bg='white')
entryZahl1.place(x=5, y=35, width=70, height=20)
# Label mit Aufschrift Zahl 2
labelZahl2 = Label(master=frameZahl2, bg='white', text='Zahl 2')
labelZahl2.place(x=5, y=5, width=70, height=20)
# Entry für Zahl 2
entryZahl2 = Entry(master=frameZahl2, bg='white', width='8')
entryZahl2.place(x=5, y=35, width=70, height=20)
# Button zum Addieren
buttonPlus = Button(master=frameBerechnen, text='+', width='2')
buttonPlus.bind('<Button-1>', rechnen)
buttonPlus.place(x=5, y=5, width=30, height=30)
# Button zum Subtrahieren
buttonMinus = Button(master=frameBerechnen, text='-', width='2')
buttonMinus.bind('<Button-1>', rechnen)
buttonMinus.place(x=45, y=5, width=30, height=30)
# Button zum Multiplizieren
buttonMal = Button(master=frameBerechnen, text='*', width='2')
buttonMal.bind('<Button-1>', rechnen)
buttonMal.place(x=85, y=5, width=30, height=30)
# Button zum Dividieren ohne Rest
buttonDurch = Button(master=frameBerechnen, text=':', width='2')
buttonDurch.bind('<Button-1>', rechnen)
buttonDurch.place(x=125, y=5, width=30, height=30)
# Button zum Rest bei der Division
buttonRest = Button(master=frameBerechnen, text='%', width='2')
buttonRest.bind('<Button-1>', rechnen)
buttonRest.place(x=165, y=5, width=30, height=30)
# Label mit Aufschrift Ergebnis
labelAufschriftErgebnis = Label(master=frameErgebnis, bg='white', text='Ergebnis')
labelAufschriftErgebnis.place(x=5, y=5, width=70, height=20)
# Label für das Ergebnis
labelErgebnis = Label(master=frameErgebnis, bg='white', width='8', text='')
labelErgebnis.place(x=5, y=35, width=70, height=20)
# Aktivierung des Fensters
tkFenster.mainloop()

Aufgabe 1

Erkläre, wie die Codeduplizierung hier vermieden wird.

Suche

v
9.1.4.9.3
www.inf-schule.de/software/gui/entwicklung_tkinter/ereignisverarbeitung/behandlung
www.inf-schule.de/9.1.4.9.3
www.inf-schule.de/@/page/oY3fnt24S421n1K4

Rückmeldung geben