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
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 vorliegen 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.