ppt - Informatik

Download Report

Transcript ppt - Informatik

Grafische Benutzeroberflächen
Klaus Becker
2013
2
Grafische Benutzeroberflächen
3
Teil 1
Benutzerfreundlichkeit
4
Zwei Programme im Vergleich
Aufgaben (siehe I: 1.8.1.1):
(1) Teste selbst die beiden Programme.
(2) Worin unterscheiden sich die
Programme? Beurteile die
Benutzerfreundlichkeit der beiden
Programme. Welche Kriterien zur
Beurteilung der Benutzerfreundlichkeit von
Programmen hast du in (b) benutzt?
(3) Benutze den Fragebogen nach der
ISONORM zur Beurteilung der
Benutzerfreundlichkeit der Programme.
5
Interaktion mit dem Benutzer
multimediale, asynchrone
Benutzeroberfläche
textbasierte, synchronisierte
Benutzeroberfläche
6
Fachkonzept - Software-Ergonomie
Die Software-Ergonomie befasst sich mit der Gestaltung benutzerfreundlicher ComputerProgramme. Ziel ist es, die Zusammenarbeit zwischen Mensch und Maschine so zu gestalten,
dass nicht der Mensch sich an den Gegebenheiten der Maschine orientieren muss, sondern
dass umgekehrt die Maschine eine Kommunikationsschnittstelle zur Verfügung stellt, die sich
an den Bedürfnissen der sie bedienenden Menschen orientiert.
Kriterien zur Beschreibung von Benutzerfreundlichkeit:
 Aufgabenangemessenheit: Das Programm konzentriert sich auf die eigentliche Aufgabe und
minimiert unnötige Interaktionen.
 Selbstbeschreibungsfähigkeit: Der Programm liefert die zur Bedienung erforderlichen Hilfen
und Rückmeldungen.
 Steuerbarkeit: Das Programm gibt dem Benutzer die Möglichkeit, mit Hilfe von Dialogen den
Ablauf zu steuern.
 Erwartungskonformität: Das Programm ist auf die Erwartungen der intendierten Benutzer
abgestimmt.
 Fehlertoleranz: Das Programm erkennt fehlerhafte Bedienungen und hilft bei der Korrektur.
 Individualisierbarkeit: Das Programm lässt sich an individuelle Bedürfnisse anpassen.
 Lernförderlichkeit: Das Programm unterstützt den Benutzer beim Erlernen der
Funktionalitäten.
7
Teil 2
Aufbau und Verhalten
8
Analyse einer GUI
Mit dem Programm "Anhalteweg" kann ein Benutzer testen, wie gut er/sie den Anhalteweg
eines Autos abschätzen kann.
Ziel ist es herauszufinden, wie eine graphische Benutzeroberfläche (GUI) aufgebaut ist und
wie ihr Verhalten zustande kommt. Bearbeiten Sie die Aufgaben des Abschnitts 1.8.2.
9
Analyse einer GUI
Aufgabe:
(a) Teste das Programm gui_anhalteweg.pyw.
(b) Eine Benutzeroberfläche ist in der Regel aus
verschiedenen grafischen Komponenten aufgebaut. Oft
findet man darunter Schriftfelder (Label-Komponenten),
Eingabefelder (Entry-Komponenten) und Schaltflächen
(Button-Komponenten). Welche dieser Komponenten
kommen in der gezeigten Benutzeroberfläche vor? Welche
Funktion erfüllen sie - welche dienen zur Eingabe,
Verarbeitung und Ausgabe von Daten, welche zur
Information des Benutzers?
(c) Eine Benutzeroberfläche bietet einem Benutzer in der
Regel verschiedene Möglichkeiten der Interaktion an.
Welche Aktionen kann ein Benutzer hier ausführen?
10
Analyse einer GUI
Aufgabe: Analysiere den Quelltext und versuche, den Komponenten der Benutzeroberfläche
die zugehörigen Bezeichner im Quelltext zuzuordnen.
from tkinter import *
# Ereignisverarbeitung
Auszug aus dem Quelltext
def Button_Berechnen_Click():
# Übernahme der Daten
geschwindigkeit = float(entryGeschwindigkeit.get())
# Verarbeitung der Daten
reaktionsweg = (geschwindigkeit/10)*3
bremsweg = (geschwindigkeit/10) * (geschwindigkeit/10)
anhalteweg = reaktionsweg + bremsweg
# Anzeige der Daten
anzeigeReaktionsweg = '%.2f'%(reaktionsweg)
labelWertReaktionsweg.config(text=anzeigeReaktionsweg)
anzeigeBremsweg = '%.2f'%(bremsweg)
labelWertBremsweg.config(text=anzeigeBremsweg)
anzeigeAnhalteweg = '%.2f'%(anhalteweg)
labelWertAnhalteweg.config(text=anzeigeAnhalteweg)
# Erzeugung des Fensters
tkFenster = Tk()
tkFenster.title('Anhalteweg')
tkFenster.geometry('300x287')
# Rahmen für die Überschrift
frameUeberschrift = Frame(master=tkFenster,
background='#889E9D')
frameUeberschrift.place(x=5, y=5, width=290, height=45)
…
G(raphical) U(ser) I(interface)
11
Fachkonzept - GUI
Eine grafische Benutzeroberfläche (auch kurz GUI für Graphical User Interface) ist aus
Komponenten aufgebaut. Jede Komponente wird mit einem grafische Symbol dargestellt.
12
Fachkonzept - GUI-Komponente
Grafische Benutzeroberflächen können u. a.
folgende Komponenten haben:
 Fenster: Eine GUI kann aus einem oder
mehreren Fenstern bestehen.
 Rahmen / Tafel: Rahmen (bzw. Tafeln) dienen
als Behälter für andere Komponenten.
 Schaltfäche (Button): Mit Schaltflächen werden
in der Regel Programmaktionen ausgelöst.
 Schriftfeld (Label): Schriftfelder dienen dazu,
Texte auf dem Bildschirm darzustellen.
 Eingabefeld: In Eingabefelder kann der
Benutzer Zeichenketten eingeben.
 Leinwand (Canvas): Eine Leinwand ist ein
Bereich, in dem man z. B. Figuren zeichnen und
Bilder anzeigen kann
 Textfeld: Ein Textfeld ist ein Eingabebereich, in
den mehrzeilige Texte geschrieben werden
können.
 ...
GUI-Komponenten werden auch
Widgets genannt.
13
Fachkonzept - GUI-Objekt
Ein Objekt ist eine Einheit, die Daten verwalten und verarbeiten kann. Jedes Objekt ist einer
Klasse zugeordnet. Diese legt den Aufbau des Objekts genau fest. Ein Objekt muss erzeugt
werden, bevor es zur Datenverwaltung und -verarbeitung benutzt werden kann. Die
zugehörige Klasse liefert den hierzu benötigten Bauplan.
Komponenten einer Benutzeroberfläche werden programmtechnisch durch Objekte (im Sinne
der objektorientierten Programmierung) dargestellt. Zu jeder Komponente gibt es ein
entsprechendes GUI-Objekt, das die Daten und Operationen der Komponente verwaltet.
14
Fachkonzept - GUI-Objekt
objektname = GUIKlasse(...)
Erzeugung eines GUI-Objekts
...
# Erzeugung des Fensters
tkFenster = Tk()
...
# Rahmen für die Überschrift
frameUeberschrift = Frame(master=tkFenster, background='#889E9D')
...
# Eingabefeld für die Geschwindigkeit
entryGeschwindigkeit = Entry(master=frameEingaben)
...
# Schaltfläche Berechnen
buttonBerechnen = Button(master=frameVerarbeitung, text='berechnen', command=...)
...
# Label für den Wert des Reaktionswegs
labelWertBremsweg = Label(master=frameAusgaben, background='white', text='')
...
15
Fachkonzept - GUI-Objekt
GUI-Komponenten haben Eigenschaften wie z. B. eine bestimmte Hintergrundfarbe. Zur
Verwaltung solcher Eigenschaften haben die zugehörigen Objekte Attribute, denen ein
bestimmter Wert zugewiesen werden kann.
Attribute
...
# Label für die Überschrift
labelUeberschrift = Label(master=frameUeberschrift,
background='white',
text='Anhalteweg eines Autos')
...
Attributwerte
16
Fachkonzept - GUI-Objekt
Zur Verarbeitung der verwalteten Daten stellen Objekte Operationen (man sagt auch
Methoden) bereit.
objektname.operation
Aktivierung einer Operation
def Button_Berechnen_Click():
Objekt
Operation
# Übernahme der Daten
geschwindigkeit = float(entryGeschwindigkeit.get())
# Verarbeitung der Daten
reaktionsweg = (geschwindigkeit/10)*3
bremsweg = (geschwindigkeit/10) * (geschwindigkeit/10)
anhalteweg = reaktionsweg + bremsweg
# Anzeige der Daten
anzeigeReaktionsweg = '%.2f'%(reaktionsweg)
labelWertReaktionsweg.config(text=anzeigeReaktionsweg)
anzeigeBremsweg = '%.2f'%(bremsweg)
labelWertBremsweg.config(text=anzeigeBremsweg)
anzeigeAnhalteweg = '%.2f'%(anhalteweg)
labelWertAnhalteweg.config(text=anzeigeAnhalteweg)
17
Fachkonzept - Ereignissteuerung
Ein Ereignis (engl. event) ist eine Zustandsänderung in einem System, die registriert und
verarbeitet werden kann.
Ereignisse können durch Benutzer ausgelöst werden:
 Der Benutzer klickt auf auf die Schaltfläche.
 Der Benutzer schließt das Fenster.
 Der Benutzer tippt ein Zeichen in ein Eingabefeld.
 Der Benutzer bewegt die Maus über eine Komponenten.
 …
Ereignisse können auch systemintern ausgelöst werden:
 Ein Zeitpunkt wird erreicht.
 Ein Fehler tritt auf.
 …
Fachkonzept - Ereignissteuerung
18
Ereignisse, die von Interesse sind, werden mit einer Prozedur zur Ereignisbehandlung (einem
sog. Eventhandler) verknüpft.
Wiederhole:
Ereignisschleife
wenn ein Ereignis eintritt:
führe die zugeordneten Prozedur zur Ereignisbehandlung aus
def Button_Berechnen_Click():
...
Ereignisbehandlungsprozedur
# Erzeugung des Fensters
tkFenster = Tk()
...
buttonBerechnen = Button(master=frameVerarbeitung,
text='berechnen',
command=Button_Berechnen_Click)
...
# Aktivierung des Fensters
Aktierung der Ereignisschleife
tkFenster.mainloop()
19
Laufzeitfehler
Aufgabe:
(a) Teste, wie das Programm „Anhalteweg“ reagiert, wenn man unsinnige Eingaben macht.
(b) Die Fehlermeldung liefert einen Hinweis, warum es hier zum Programmabbruch kommt.
Erkläre die Ursache für den Programmabbruch.
20
Fachkonzept - Laufzeitfehler
Laufzeitfehler sind Fehlersituationen, die während der Ausführung eines Programms auftreten.
Beispiele:
- Eine Operation soll mit Daten ausgeführt werden, deren Typ nicht passt.
- Eine Division durch 0 soll ausgeführt werden.
- Eine Datei soll geladen werden, die nicht vorhanden ist.
- ...
>>>
Exception in Tkinter callback
Traceback (most recent call last):
File ...
return self.func(*args)
File ... in Button_Berechnen_Click
geschwindigkeit = float(entryGeschwindigkeit.get())
ValueError: invalid literal for float(): gering
21
try-except-Anweisung
def Button_Berechnen_Click():
try:
# Übernahme der Daten
geschwindigkeit = float(entryGeschwindigkeit.get())
# Verarbeitung der Daten
reaktionsweg = (geschwindigkeit/10)*3
bremsweg = (geschwindigkeit/10) * (geschwindigkeit/10)
anhalteweg = reaktionsweg + bremsweg
# Anzeige der Daten
anzeigeReaktionsweg = '%.2f'%(reaktionsweg)
labelWertReaktionsweg.config(text=anzeigeReaktionsweg)
anzeigeBremsweg = '%.2f'%(bremsweg)
labelWertBremsweg.config(text=anzeigeBremsweg)
anzeigeAnhalteweg = '%.2f'%(anhalteweg)
labelWertAnhalteweg.config(text=anzeigeAnhalteweg)
except:
entryGeschwindigkeit.delete(0, END)
try:
[Anweisungen]
except:
[Anweisungen]
22
Übungen
Verändere das Programm "Anhalteweg eines Autos" wie folgt:
 Entferne die Komponente zur Eingabe des geschätzten Anhaltewegs, indem du das Objekt
nicht erzeugst. Lösche hierzu die passende Anweisung im Quelltext.
 Die berechneten Wege sollen deutlicher hervorgehoben werden, z. B., indem sie mit einer
anderen Farbe angezeigt werden. Welche Attributwerte müssen hierzu gesetzt werden?
 Wenn der geschätzte Anhalteweg zu gering ist, dann soll der Hintergrund der Komponente
rot eingefärbt werden. Dies soll mit einer zweiten Schaltfläche ausgelöst werden. Hinweis:
Will man auf Attributwerte eines Label-Objekts zugreifen, so lässt sich dies mit der
Operation cget(...) durchführen. Beispielsweise liefert die Anweisung label.cget('text') den
aktuellen Wert des Attributs text des Label-Objekts label.
23
Teil 3
Miniprojekt chuck-a-luck
24
Das Spiel chuck-a-luck
Der Spieler / die Spielerin zahlt zuerst einen Dollar (Cent) als Einsatz. Diesen setzt er / sie auf
eine Zahl des Spielfeldes. Anschließend wirft er / sie drei Würfel. Jetzt wird bestimmt, wie
viele Würfel mit der gesetzten Spielzahl übereinstimmen. Gibt es keine Übereinstimmungen,
dann ist der Einsatz verloren. Ansonsten wird erhält der Spieler / die Spielerin den Einsatz
zurück und zusätzlich für jede Übereinstimmung einen Dollar (Cent).
25
Eine GUI zum Spiel chuck-a-luck
Aufgabe
(a) Entwickle einen Vorschlag zur Gestaltung einer GUI zum Spiel chuck-a-luck. Orientiere
dich dabei an dem realen Spiel und mache dir klar, in welcher Weise ein Benutzer mit der GUI
interagieren soll. Dokumentiere deinen Vorschlag, indem du die GUI skizzierst.
(b) Strukturiere deinen GUI-Vorschlag, indem du die Elemente der GUI mit GUI-Komponenten
beschreibst.
26
Entwicklung einer GUI
Zur Orientierung:
Du sollst hier selbst eine grafische Benutzeroberfäche zum Spiel chuck-a-luck entwickeln.
Indem du dir jeweils das benötigte Wissen in einem der folgenden Abschnitten besorgst,
kannst du die gewünschte grafische Benutzeroberfläche Schritt für Schritt erstellen. Dabei
lernst du auch, wie man die wichtigsten GUI-Komponenten mit Python realisieren kann.
27
Eine einfache GUI
In einer ersten Version soll es darum gehen, eine möglichst einfache, aber funktionierende
GUI zu implementieren. Z.B.:
Aufgabe:
Entwickle eine einfache Spiel-GUI mit Hilfe der Informationen auf den folgenden Abschnitte
von www.inf-schule.de:
 Erzeugung eines Fensters
 Anzeige von Text und Daten
 Anklicken von Schaltflächen
 Eingabe von Daten
28
Eine einfache GUI
Aufgabe:
Überarbeite das bisher benutzte Layout der GUI. Benutze die Informationen des
entsprechenden Abschnitts von www.inf-schule.de.
29
Eine benutzerfreundlichere Eingabe
Die Eingabe der Spielzahl über ein Eingabefeld birgt die Gefahr, dass der Benutzer unsinnige
Werte eingibt. Statt einer möglichen Würfelzahl kann der Benutzer in der bisher entwickelten
GUI beliebige Zeichenketten eingeben.
Aufgabe:
Eine benutzerfeundliche Oberfläche sollte solche Fehleingaben verhindern. Eine Möglichkeit
besteht darin, dem Benutzer nur eine Auswahl an erlaubten Eingaben anzubieten.
Informiere dich auf www.inf-schule.de, wie man solche Auswahlkomponenten realisiert.
30
Eine benutzerfreundlichere Ausgabe
Anschaulicher werden Würfelergebnisse, wenn man sie mit Würfelbildern darstellt.
Aufgabe:
Implementiere eine GUI mit verbesserter Ausgabe. Bearbeite hierzu die Abschnitte
Einbindung von Bildern.
31
Eine benutzerfreundlichere Kontrolle
In der bisher entwickelten Version hat man als Benutzer(in) die Möglichkeit, solange zu
würfeln, bis die zuvor gesetzte Spielzahl gefallen ist. Man kann auch nachträglich die
Spielzahl abändern und sich dann den Gewinn auszahlen lassen.
Im realen Spiel sind solche Verletzungen des Spielablaufs nicht zulässig. Schön wäre es, wenn
die GUI solche unzulässigen Abläufe ebenfalls unterbinden würde.
Die Ablaufsteuerung lässt sich realisieren, indem man die Komponenten jeweils aktiviert und
deaktiviert.
32
Eine benutzerfreundlichere Kontrolle
Wir modellieren zunächst den Spielablauf mit einem Zustandsdiagramm:
Aufgabe:
Implementiere eine GUI mit verbesserter Kontrolle. Information zum (De-)Aktivieren von
GUI-Komponenten findest du im Abschnitt Anklicken von Schaltflächen in Aufgabe 1.
33
Weiterentwicklungen
Bisher war es nur möglich, alle drei Würfel gleichzeitig zu werfen, indem der Button "Würfel
werfen" angeklickt wird. Durch einen Doppelklick auf die entsprechenden Textfelder sollen
Würfel auch einzeln geworfen werden können.
Aufgabe:
Informiere dich im Abschnitt Verarbeitung von Ereignissen, wie man Ereignisse wie einen
Doppelklick auf ein Textfeld implementiert, und entwickle die Benutzeroberfläche in der
beschriebenen Weise weiter.
34
Weiterentwicklungen
Wie hoch sind die Gewinnaussichten beim chuck-a-luck-Spiel? Um das einschätzen zu können,
muss man längere Spielserien durchführen. Günstig wäre es, wenn das chuck-a-luckProgramm dies automatisiert durchführen könnte. Der Benutzer gibt im Eingabefeld des
Zählers eine Startzahl ein (z.B. 100). Wenn man dann die Schaltfläche mit der Aufschrift
"Spiele durchführen" anklickt, dann werden so viele Spiele Schritt für Schritt durchgeführt
und angezeigt, wie die Startzahl es vorgibt.
Aufgabe:
Informiere dich im Abschnitt Animation mit einem Timer, wie man einen Timer-gesteuerten
Ablauf realisiert, und entwickle die Benutzeroberfläche in der beschriebenen Weise weiter.
35
Glücksspiele
Viele Glücksspiele wie "Mensch-ärgere-dich-nicht" werden gerne in kleiner Runde gespielt und
dienen in erster Linie dazu, Zeit gemeinsam und gesellig zu verbringen.
Bei anderen Glücksspielen wie "Lotto" oder "Poker" wird Geld eingesetzt und meist mit dem
Ziel gespielt, Gewinne zu erzielen. In der Regel führen solche Glücksspiele aber eher zu
Geldverlusten als zu größeren Geldgewinnen.
Glücksspiele, die von einer Spielbank angeboten werden, sind in aller Regel so angelegt, dass
der Spieler auf lange Sicht Geld verliert. Im Fall des Spiels "chuck a luck" verliert der Spieler
auf lange Sicht 0,08 Cents pro Spiel bei einem Einsatz von 1 Euro. Bei anderen Glücksspielen
wie "Poker" oder "Roulett" können die Verluste deutlich größer sein.
Glücksspiele wecken bei vielen Menschen Spielfreude. Bei manchen Menschen führen solche
Spiele aber zu einer unkontrollierten Spielleidenschaft bis hin zur Spielsucht. Die Folge sind
sehr oft große Verluste bis hin zu Spielschulden.
Glücksspiele - insbesondere die mit höheren Spieleinsätzen - waren daher in vielen Kulturen
verboten. Auch heute wird kommerzielles Glücksspiel nur für Erwachsene und in kontrollierter
Umgebung erlaubt.
Kommerzielles Glücksspiel wird in den Paragraphen 284 und 285 des deutschen
Strafgesetzbuches thematisiert. Bei den Regelungen zum Glücksspiel geht es vor allem
darum, eine Kommerzialisierung der natürlichen Spielleidenschaft zu kontrollieren, den
Einzelnen vor Vermögensgefährdung zu bewahren und öffentliche Haushalte zu schützen, die
meist bei Vermögensverfall der Spieler eintreten müssen.
36
Glücksspiele
Aufgabe:
Aus einem Forum für Poker-Spieler: "Ich bin 22 Jahre alt und spiele seit 2 Jahren online
Poker. Mittlerweile habe ich einige tausend Euro Schulden. Was soll ich machen, ich bin
süchtig und komme vom Pokern nicht weg? Wenn ich einen Poker-Raum betrete, dann spiele
ich mich in den Rausch und verzocke alles innerhalb von ein paar Stunden."
(a) Kann Spielen wirklich süchtig machen? Hast du schon eigene Erfahrungen gemacht oder
kannst du von Erfahrungen von Freunden oder Bekannten berichten?
(b) Diskutiere die neuen Möglichkeiten und Gefahren, die das Internet zum Thema "Spielen"
bietet.
37
Teil 4
GUI-Entwicklung mit tkinter
38
Erzeugung eines Fensters
from tkinter import *
# Erzeugung des Fensters
tkFenster = Tk()
tkFenster.title('Test')
# Aktivierung des Fensters
tkFenster.mainloop()
Erzeugung eines Tk-Objekts
39
Anzeige von Text und Daten
from tkinter import *
# Erzeugung des Fensters
tkFenster = Tk()
Erzeugung eines Label-Objekts
tkFenster.title('Kalender')
tkFenster.geometry('130x145')
Initialisierung von Attributwerten
# Label für die Anzeige der Daten
labelMonat = Label(master=tkFenster, text='Januar', fg='white', bg='gray', font=('Arial', 16))
labelMonat.place(x=5, y=5, width=120, height=20)
labelTag = Label(master=tkFenster, text='21', fg='red', bg='#FFCFC9', font=('Arial', 72))
labelTag.place(x=5, y=30, width=120, height=80)
labelWochentag = Label(master=tkFenster, text='Montag')
labelWochentag.place(x=35, y=115, width=60, height=30)
# Aktivierung des Fensters
tkFenster.mainloop()
40
Anzeige von Text und Daten
from tkinter import *
# Erzeugung des Fensters
tkFenster = Tk()
tkFenster.title('Kalender')
tkFenster.geometry('130x85')
# Label für die Anzeige der Daten
…
labelTag = Label(master=tkFenster, text='21', fg='red', bg='#FFCFC9', font=('Arial', 24))
labelTag.place(x=5, y=30,
width=55,
height=50)
lesender
Zugriff
auf ein Attribut
schriftfarbe = labelTag.cget('fg')
hintergrundfarbe = labelTag.cget('bg')
schriftformat = labelTag.cget('font')
# lesender Zugriff auf Attribute von labelTag
# lesender Zugriff auf Attribute von labelTag
# lesender Zugriff auf Attribute von labelTag
labelMonat = Label(master=tkFenster, text='01')
labelMonat.config(fg=schriftfarbe)
# schreibender Zugriff auf Attribute von labelMonat
labelMonat.config(bg=hintergrundfarbe) # schreibender Zugriff auf Attribute von labelMonat
labelMonat.config(font=schriftformat) # schreibender Zugriff auf Attribute von labelMonat
labelMonat.place(x=70, y=30, width=55, height=50)
schreibenderZugriff auf ein Attribut
# Aktivierung des Fensters
tkFenster.mainloop()
41
Anklicken von Schaltflächen
from tkinter import *
Ereignisbehandlung
# Ereignisbehandlung
def buttonWeiterClick():
stand = int(labelZahl.cget('text'))
stand = stand + 1
labelZahl.config(text=str(stand))
…
# GUI-Objekte
# Fenster
tkFenster = Tk()
tkFenster.title('Zähler')
tkFenster.geometry('170x125')
# Label
labelZahl = Label(master=tkFenster, text='0', bg='gray', font=('Arial', 36))
labelZahl.place(x=5, y=5, width=160, height=80)
# Button
buttonWeiter = Button(master=tkFenster, text='weiter', bg='#D5E88F',
command=buttonWeiterClick)
Erzeugung eines
buttonWeiter.place(x=115, y=90, width=50, height=30)
Button-Objekts
…
42
Anklicken von Schaltflächen
from tkinter import *
Schritt 1:
Erst werden die benötigten Daten
von Attributen betreffender GUIObjekte übernommen und in
Hilfsvariablen
zwischengespeichert. Beachte,
dass hier oft Tyanpassungen
erforderlich sind.
# Ereignisbehandlung
def buttonWeiterClick():
# Schritt 1
stand = int(labelZahl.cget('text'))
# Schritt 2
stand = stand + 1
# Schritt 3
labelZahl.config(text=str(stand))
…
Datenverarbeitungsmuster
Schritt 2:
Die jetzt mit Hilfe von Variablen
erfassten Daten werden mit Hilfe
geeigneter Anweisungen
verarbeitet.
Schritt 3:
# Button
Die Ergebnisse der Verarbeitung
buttonWeiter = Button(master=tkFenster, text='weiter', bg='#D5E88F',
werden zur Anzeige auf dem
command=buttonWeiterClick)
buttonWeiter.place(x=115, y=90, width=50, height=30) Bildschirm an geeignete GUIObjekte weitergegeben. Auch hier
…
können Typumwandlungen
erforderlich sein.
43
Eingabe von Daten
from tkinter import *
# Ereignisbehandlung
def buttonBerechnenClick():
# Übernahme der Daten
gewicht = float(entryGewicht.get())
groesse = float(entryGroesse.get())
# Verarbeitung der Daten
bmi = gewicht/(groesse*groesse)
bmiAnzeige = str(round(bmi*10)/10)
# Anzeige der Daten
labelBMI.config(text=bmiAnzeige)
…
# Label mit Aufschrift Gewicht
labelGewicht = Label(master=tkFenster, bg='#FFCFC9', text='Gewicht in kg:')
labelGewicht.place(x=54, y=24, width=100, height=27)
# Entry für das Gewicht
Erzeugung eines
entryGewicht = Entry(master=tkFenster, bg='white')
Entry-Objekts
entryGewicht.place(x=164, y=24, width=40, height=27)
…
# Button zum Berechnen
buttonBerechnen = Button(master=tkFenster, bg='#FBD975', text='berechnen',
command=buttonBerechnenClick)
…
44
Eingabe von Daten
from tkinter import *
# Ereignisverarbeitung
def buttonVerdoppelnClick():
# Verwaltung der Daten
zahl = int(entryZahl.get())
# Verarbeitung der Daten
zahl = zahl * 2
Entry-Operationen
# Anzeige der Daten
entryZahl.delete(0, 'end')
entryZahl.insert(0, str(zahl))
# Erzeugung des Fensters
tkFenster = Tk()
tkFenster.title('Test')
tkFenster.geometry('120x110')
# Eingabefeld für die Zahl
entryZahl = Entry(master=tkFenster, bg='white')
entryZahl.place(x=45, y=40, width=30, height=30)
# Button zum Auswerten
buttonVerdoppeln = Button(master=tkFenster, text='verdoppeln',
command=buttonVerdoppelnClick)
buttonVerdoppeln.place(x=10, y=80, width=100, height=20)
# Aktivierung des Fensters
tkFenster.mainloop()
Erzeugung eines
Entry-Objekts
45
Gestaltung des Layout – place-Manager
# Fenster
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
# Label mit Aufschrift Zahl 1
labelZahl1 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 1')
labelZahl1.place(x=10, y=10, width=70, height=20)
# Entry für Zahl 1
entryZahl1 = Entry(master=tkFenster, bg='white')
entryZahl1.place(x=10, y=40, width=70, height=20)
# Label mit Aufschrift Zahl 2
labelZahl2 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 2')
labelZahl2.place(x=120, y=10, width=70, height=20)
…
# Label mit Aufschrift Ergebnis
labelAufschriftErgebnis = Label(master=tkFenster, bg='#D5E88F', text='Ergebnis')
labelAufschriftErgebnis.place(x=65, y=120, width=70, height=20)
# Label für das Ergebnis
labelErgebnis = Label(master=tkFenster, bg='white', width='8', text='')
labelErgebnis.place(x=65, y=150, width=70, height=20)
# Aktivierung des Fensters
tkFenster.mainloop()
46
Gestaltung des Layout – mit Frames
# Fenster
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
# Label mit Aufschrift Zahl 1
labelZahl1 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 1')
labelZahl1.place(x=10, y=10, width=70, height=20)
# Entry für Zahl 1
entryZahl1 = Entry(master=tkFenster, bg='white')
entryZahl1.place(x=10, y=40, width=70, height=20)
# Fenster
tkFenster = Tk()
Erzeugung eines
tkFenster.title('Rechner')
Frame-Objekts
tkFenster.geometry('200x180')
# Rahmen
frameZahl1 = Frame(master=tkFenster, bg='#FFCFC9')
frameZahl1.place(x=5, y=5, 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)
…
47
Gestaltung des Layout – place-Manager
# Fenster
Pixelkoordinatensysteme
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
# Rahmen
…
frameErgebnis = Frame(master=tkFenster, bg='#D5E88F')
frameErgebnis.place(x=60, y=115, width=80, height=60)
…
# 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()
48
Gestaltung des Layout – place-Manager
Master-Slave-Hierarchie
tkFenster
master
slave
frameErgebnis
master
slave
labelAufschriftErgebnis
tkFenster = Tk()
…
frameErgebnis = Frame(master=tkFenster, bg='#D5E88F')
…
# Label mit Aufschrift Ergebnis
labelAufschriftErgebnis = Label(master=frameErgebnis, …)
…
49
Gestaltung des Layout – pack-Manager
# Fenster
tkFenster = Tk()
tkFenster.title('Rechner')
# Frames
frameEingaben = Frame(master=tkFenster)
frameZahl1 = Frame(master=frameEingaben, bg='#FFCFC9')
frameZahl2 = Frame(master=frameEingaben, bg='#FFCFC9')
frameBerechnen = Frame(master=tkFenster, bg='#FBD975')
frameAusgaben = Frame(master=tkFenster)
frameErgebnis = Frame(master=frameAusgaben, bg='#D5E88F')
frameEingaben.pack(fill='x')
frameBerechnen.pack(fill='x')
frameAusgaben.pack(fill='x')
frameErgebnis.pack(padx='5', pady='5')
frameZahl1.pack(side='left', padx='5', pady='5')
frameZahl2.pack(side='right', padx='5', pady='5')
# Label mit Aufschrift Zahl 1
labelZahl1 = Label(master=frameZahl1, bg='white', text='Zahl 1')
labelZahl1.pack(padx='5', pady='5', fill='x')
# Entry für Zahl 1
entryZahl1 = Entry(master=frameZahl1, bg='white', width='8')
entryZahl1.pack(padx='5', pady='5')
…
50
Gestaltung des Layout – grid-Manager
# Fenster
tkFenster = Tk()
tkFenster.title('Rechner')
# Label mit Aufschrift Zahl 1
labelZahl1 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 1')
labelZahl1.grid(row=0, column=0, padx='5', pady='5', sticky='ew')
# Entry für Zahl 1
entryZahl1 = Entry(master=tkFenster, bg='white', width='8')
entryZahl1.grid(row=0, column=1, padx='5', pady='5', sticky='ew')
# Label mit Aufschrift Zahl 2
labelZahl2 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 2')
labelZahl2.grid(row=2, column=0, padx='5', pady='5', sticky='ew')
# Entry für Zahl 2
entryZahl2 = Entry(master=tkFenster, bg='white', width='8')
entryZahl2.grid(row=2, column=1, padx='5', pady='5', sticky='ew')
# Button zum Addieren
buttonPlus = Button(master=tkFenster, text='+', width='2', bg='#FBD975',
command=buttonPlusClick)
buttonPlus.grid(row=0, column=2, padx='5', pady='5')
# Button zum Subtrahieren
buttonMinus = Button(master=tkFenster, text='-', width='2', bg='#FBD975',
command=buttonMinusClick)
…
51
Einbindung von Bildern
…
# Ereignisverarbeitung
def buttonWuerfelnClick():
# Verwaltung und Verarbeitung der Daten
augen = randint(1,6)
# Anzeige der Daten
if augen == 1:
labelWuerfel.config(image=imageWuerfel1)
elif augen == 2:
…
# Erzeugung der GUI-Komponenten
…
# Bilder
imageWuerfel1 = PhotoImage(file='w1.gif')
Erzeugung eines
imageWuerfel2 = PhotoImage(file='w2.gif')
PhotoImage-Objekts
…
# Label Würfel mit Bild
labelWuerfel = Label(master=frameWuerfel, image=imageWuerfel1)
labelWuerfel.place(x=40, y=25, width=30, height=30)
…
52
Einbindung von Bildern
…
# Ereignisverarbeitung
def buttonWuerfelnClick():
# Verwaltung und Verarbeitung der Daten
augen = randint(1,6)
# Anzeige der Daten
labelWuerfel.config(image=imageListe[augen-1])
# Erzeugung der GUI-Komponenten
…
# Bilder
imageListe = [
PhotoImage(file='w1.gif'),
PhotoImage(file='w2.gif'),
PhotoImage(file='w3.gif'),
Erzeugung von
PhotoImage(file='w4.gif'),
PhotoImage-Objekten
PhotoImage(file='w5.gif'),
PhotoImage(file='w6.gif')
]
# Label Würfel mit Bild
labelWuerfel = Label(master=frameWuerfel, image=imageListe[0])
…
53
Eine Leinwand für Grafiken
...
# Erzeugung des Fensters
fenster = Tk()
Erzeugung eines
fenster.title('Ampel')
Canvas-Objekts
fenster.geometry('170x240')
# Zeichenfläche
canvas = Canvas(master=fenster, bg='blue')
canvas.place(x=5, y=5, width=160, height=190)
# Ampelkasten
canvas.create_rectangle(65, 10, 95, 110, fill='black')
# Stange
canvas.create_rectangle(78, 110, 82, 180, fill='black')
# Rot-Licht
id_rot = canvas.create_oval(70, 20, 90, 40, fill='red')
# Gelb-Licht
id_gelb = canvas.create_oval(70, 50, 90, 70, fill='gray')
# Grün-Licht
id_gruen = canvas.create_oval(70, 80, 90, 100, fill='gray')
# Button zum Weiterschalten
buttonWeiter = Button(master=fenster, text='weiter', command=buttonWeiterClick)
buttonWeiter.place(x=5, y=210, width=160, height=20)
# Ereignisschleife starten
fenster.mainloop()
54
Eine Leinwand für Grafiken
from tkinter import *
# Ereignisbehandlung
def buttonWeiterClick():
if canvas.itemcget(id_rot, 'fill') == 'red' and \
canvas.itemcget(id_gelb, 'fill') == 'gray' and \
canvas.itemcget(id_gruen, 'fill') == 'gray':
# aktueller Zustand: rot
# naechster Zustand: rotgelb
canvas.itemconfigure(id_gelb, fill='yellow')
elif canvas.itemcget(id_rot, 'fill') == 'red' and \
canvas.itemcget(id_gelb, 'fill') == 'yellow' and \
canvas.itemcget(id_gruen, 'fill') == 'gray':
# aktueller Zustand: rotgelb
# naechster Zustand: grün
canvas.itemconfigure(id_rot, fill='gray')
canvas.itemconfigure(id_gelb, fill='gray')
canvas.itemconfigure(id_gruen, fill='green')
…
…
55
Animation mit einem Timer
from tkinter import *
# Ereignisverarbeitung
def buttonWeiterClick():
if canvas.itemcget(id_rot, 'fill') == 'red' and \
canvas.itemcget(id_gelb, 'fill') == 'gray' and \
canvas.itemcget(id_gruen, 'fill') == 'gray':
# aktueller Zustand: rot
# naechster Zustand: rotgelb
canvas.itemconfigure(id_gelb, fill='yellow')
elif canvas.itemcget(id_rot, 'fill') == 'red' and \
canvas.itemcget(id_gelb, 'fill') == 'yellow' and \
canvas.itemcget(id_gruen, 'fill') == 'gray':
# aktueller Zustand: rotgelb
# naechster Zustand: grün
canvas.itemconfigure(id_rot, fill='gray')
canvas.itemconfigure(id_gelb, fill='gray')
canvas.itemconfigure(id_gruen, fill='green')
…
canvas.after(1000, buttonWeiterClick)
…
56
Animation mit einem Timer
from tkinter import *
# Ereignisbehandlung
def buttonCountdownClick():
stand = int(labelZahl.cget('text'))
if stand > 0:
# Zähler aktualisieren
stand = stand - 1
labelZahl.config(text=str(stand))
tkFenster.after(1000, buttonCountdownClick)
# Fenster
tkFenster = Tk()
tkFenster.title('Countdown')
tkFenster.geometry('170x125')
# Label
labelZahl = Label(master=tkFenster, text='10', bg='gray', font=('Arial', 36))
labelZahl.place(x=5, y=5, width=160, height=80)
# Button
buttonCountdown = Button(master=tkFenster, text='countdown', bg='#FBD975',
command=buttonCountdownClick)
buttonCountdown.place(x=5, y=90, width=160, height=30)
# Aktivierung des Fensters
tkFenster.mainloop()
57
Verarbeitung von Ereignissen
from tkinter import *
Behandlung des Ereignisses
# Ereignisbehandlung
def buttonWeiterClick():
stand = int(labelZahl.cget('text'))
stand = stand + 1
labelZahl.config(text=str(stand))
…
# GUI-Objekte
Anbinden einer Ereignisbehandlungsmethode an eine GUI-Kmponente
…
# Button
buttonWeiter = Button(master=tkFenster, text='weiter', bg='#D5E88F',
command=buttonWeiterClick)
buttonWeiter.place(x=115, y=90, width=50, height=30)
buttonZurueck = Button(master=tkFenster, text='zurück', bg='#FFCFC9',
command=buttonZurueckClick)
buttonZurueck.place(x=5, y=90, width=50, height=30)
buttonNull = Button(master=tkFenster, text='Null', bg='#FBD975', command=buttonNullClick)
buttonNull.place(x=60, y=90, width=50, height=30)
# Aktivierung des Fensters
tkFenster.mainloop()
58
Verarbeitung von Ereignissen
from tkinter import *
Behandlung des Ereignisses
# Ereignisbehandlung
def buttonWeiterClick(event):
stand = int(labelZahl.cget('text'))
stand = stand + 1
labelZahl.config(text=str(stand))
…
# GUI-Objekte
Anbinden einer Ereignisbehandlungsmethode an eine GUI-Kmponente
…
# Button
buttonWeiter = Button(master=tkFenster, text='weiter', bg='#D5E88F')
buttonWeiter.bind('<Button-1>', buttonWeiterClick)
buttonWeiter.place(x=115, y=90, width=50, height=30)
buttonZurueck = Beschreibung
Button(master=tkFenster,
text='zurück', bg='#FFCFC9')
des Ereignisses
buttonZurueck.bind('<Button-1>', buttonZurueckClick)
buttonZurueck.place(x=5, y=90, width=50, height=30)
buttonNull = Button(master=tkFenster, text='Null', bg='#FBD975')
buttonNull.bind('<Button-1>', buttonNullClick)
buttonNull.place(x=60, y=90, width=50, height=30)
# Aktivierung des Fensters
tkFenster.mainloop()
59
Verarbeitung von Ereignissen
from tkinter import *
# Ereignisbehandlung
def linksVerschieben(event):
(x0, y0, x1, y1) = tuple(canvas.coords(id_kreis))
if x0 >= 10:
canvas.coords(id_kreis, (x0-10, y0, x1-10, y1))
…
# Erzeugung der Komponenten
…
# Grafikobjekte
id_kreis = canvas.create_oval(100, 100, 120, 120, fill='red')
# Ereignisse
tkFenster.bind('<KeyPress-g>', vergroessern)
tkFenster.bind('<KeyPress-k>', verkleinern)
tkFenster.bind('<KeyPress-Up>', obenVerschieben)
tkFenster.bind('<KeyPress-Down>', untenVerschieben)
tkFenster.bind('<KeyPress-Left>', linksVerschieben)
tkFenster.bind('<KeyPress-Right>', rechtsVerschieben)
canvas.bind('<Button-1>>', plazieren)
Beschreibung von Ereignissen
canvas.bind('<Button-3>>', entfernen)
# Aktivierung der Ereignisschleife
tkFenster.mainloop()
60
Verarbeitung von Ereignissen
from tkinter import *
Behandlung von Ereignissen
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
…
# Anzeige der Daten
labelErgebnis.config(text=str(ergebnis))
…
# Button zum Addieren
buttonPlus = Button(master=frameBerechnen, text='+', width='2')
buttonPlus.bind('<Button-1>', rechnen)
…
61
Datenverwaltung mit Kontrollvariablen
from tkinter import *
# Erzeugung des Fensters
tkFenster = Tk()
tkFenster.title('Test')
tkFenster.geometry('120x130')
# Rahmen Eingabe
frameEingabe = Frame(master=tkFenster, bg='#FFCFC9')
frameEingabe.place(x=5, y=5, width=110, height=35)
# Rahmen Ausgabe
frameAusgabe = Frame(master=tkFenster, bg='#D5E88F')
frameAusgabe.place(x=5, y=45, width=110, height=80)
# Kontrollvariable
Erzeugung einer Kontrollvariable
text = StringVar()
# Entry Text
entryText = Entry(master=frameEingabe, bg='white', textvariable=text)
entryText.place(x=5, y=5, width=100, height=20)
# Label Text
labelText1 = Label(master=frameAusgabe, bg='white', font=('Arial', 8), textvariable=text)
labelText1.place(x=5, y=5, width=100, height=20)
labelText2 = Label(master=frameAusgabe, bg='white', font=('Arial', 12), textvariable=text)
labelText2.place(x=5, y=30, width=100, height=20)
labelText3 = Label(master=frameAusgabe, bg='white', font=('Arial', 16), textvariable=text)
…
62
Datenverwaltung mit Kontrollvariablen
from tkinter import *
# Ereignisverarbeitung
def buttonVerarbeitenClick():
zahl = int(text.get())
Zugriff auf eine Kontrollvariable
zahl = zahl+1
text.set(str(zahl))
# Erzeugung des Fensters
…
# Rahmen Verarbeitung
frameVerarbeitung = Frame(master=tkFenster, bg='#FBD975')
frameVerarbeitung.place(x=5, y=40, width=110, height=30)
# Kontrollvariable
text = StringVar()
text.set('0')
# Button
buttonVerarbeiten = Button(master=frameVerarbeitung, text='weiter',
command=buttonVerarbeitenClick)
buttonVerarbeiten.place(x=5, y=5, width=100, height=20)
# Label Text
labelText = Label(master=frameLabel, bg='white', textvariable=text)
labelText.place(x=5, y=5, width=100, height=20)
# Aktivierung des Fensters
tkFenster.mainloop()
63
Auswahl mit Radiobutton
from tkinter import *
…
# Rahmen Radiobutton
frameRadiobutton = Frame(master=tkFenster, bg='#FFCFC9')
frameRadiobutton.place(x=5, y=5, width=110, height=80)
# Rahmen Ausgabe
frameAusgabe = Frame(master=tkFenster, bg='#D5E88F')
frameAusgabe.place(x=5, y=90, width=110, height=30)
# Kontrollvariable
Erzeugung eines Radiobutton-Objekts
tageszeit = StringVar()
# Radiobutton
radiobutton1 = Radiobutton(master=frameRadiobutton, anchor='w',
text='morgens', value='Guten Morgen!', variable=tageszeit)
radiobutton1.place(x=5, y=5, width=100, height=20)
radiobutton2 = Radiobutton(master=frameRadiobutton, anchor='w',
text='mittags', value='Guten Tag!', variable=tageszeit)
radiobutton2.place(x=5, y=30, width=100, height=20)
…
radiobutton1.select()
# Label Text
labelText = Label(master=frameAusgabe, bg='white', textvariable=tageszeit)
labelText.place(x=5, y=5, width=100, height=20)
…
64
Auswahl mit Radiobutton
…
def auswahlClick():
anzeige = str(wert.get()) + ' Liter'
labelText.config(text=anzeige)
…
# Kontrollvariable
Verwendung einer Kontrollvariablen
wert = DoubleVar()
# Radiobutton
radiobutton1 = Radiobutton(master=frameRadiobutton, anchor='w',
text='klein', value=0.2, variable=wert,
command=auswahlClick)
radiobutton1.place(x=5, y=5, width=100, height=20)
radiobutton2 = Radiobutton(master=frameRadiobutton, anchor='w',
text='mittel', value=0.3, variable=wert,
command=auswahlClick)
radiobutton2.place(x=5, y=30, width=100, height=20)
…
radiobutton1.select()
# Label Text
labelText = Label(master=frameAusgabe, bg='white', text=str(wert.get()) + ' Liter')
labelText.place(x=5, y=5, width=100, height=20)
# Aktivierung des Fensters
tkFenster.mainloop()
65
Auswahl mit Checkbutton
…
def auswahlClick():
dezimalzahl = wert0.get() + wert1.get() + wert2.get() + wert3.get()
labelText.config(text=str(dezimalzahl))
…
wert0 = IntVar()
Verwendung mehrer Kontrollvariablen
wert1 = IntVar()
wert2 = IntVar()
wert3 = IntVar()
# Checkbutton
checkbutton0 = Checkbutton(master=frameCheckbutton, anchor='w',
text='2^0', offvalue=0, onvalue=1, variable=wert0,
command=auswahlClick)
checkbutton0.place(x=5, y=5, width=100, height=20)
checkbutton1 = Checkbutton(master=frameCheckbutton, anchor='w',
text='2^1', offvalue=0, onvalue=2, variable=wert1,
command=auswahlClick)
checkbutton1.place(x=5, y=30, width=100, height=20)
checkbutton2 = Checkbutton(master=frameCheckbutton, anchor='w',
text='2^2', offvalue=0, onvalue=4, variable=wert2,
command=auswahlClick)
checkbutton2.place(x=5, y=55, width=100, height=20)
…
66
Auswahl aus einer Listbox
…
def buttonVerarbeitenClick():
listeAusgewaehlt = listboxNamen.curselection()
itemAusgewaehlt = listeAusgewaehlt[0]
nameAusgewaehlt = listboxNamen.get(itemAusgewaehlt)
textBegruessung = 'Hallo ' + nameAusgewaehlt +'!'
labelText.config(text=textBegruessung)
Erzeugung eines ListBox-Objekts
…
# Listbox
listboxNamen = Listbox(master=frameListbox, selectmode='browse')
listboxNamen.insert('end', 'Anna')
listboxNamen.insert('end', 'Bernd')
listboxNamen.insert('end', 'Clara')
listboxNamen.insert('end', 'Dominik')
listboxNamen.place(x=5, y=5, width=100, height=70)
…
67
Ein Textfeld
…
def buttonVerschluesselnClick():
klartext = textfeld1.get('1.0', 'end').strip()
…
textfeld2.delete('1.0', 'end')
textfeld2.insert('1.0', geheimtext)
…
# Textfelder
textfeld1 = Text(master=tkFenster, width=39, height=4, wrap='word')
textfeld1.place(x=8, y=8)
scrollbar1 = Scrollbar(master=tkFenster)
scrollbar1.place(x=342, y=8, width=10, height=68)
textfeld1.config(yscrollcommand=scrollbar1.set)
scrollbar1.config(command=textfeld1.yview)
textfeld2 = Text(master=tkFenster, width=39, height=4, wrap='word')
textfeld2.place(x=8, y=118)
scrollbar2 = Scrollbar(master=tkFenster)
scrollbar2.place(x=342, y=118, width=10, height=68)
textfeld2.config(yscrollcommand=scrollbar2.set)
scrollbar2.config(command=textfeld2.yview)
…
Erzeugung eines
Textfeld-Objekts
68
Fenster öffnen und schließen
…
def buttonBerechnenClick():
try:
gewicht = float(entryGewicht.get())
…
except:
# Ereignisbehandlung
def buttonOkClick():
Fenster-Objekt
tkFensterFehler.quit()
vernichten
tkFensterFehler.destroy()
# Neues Fenster öffnen
tkFensterFehler = Tk()
Fenster-Objekt
tkFensterFehler.title('Fehler')
erzeugen
tkFensterFehler.geometry('160x60')
# Label mit der Fehlermeldung
labelFehler = Label(master=tkFensterFehler,
text='Keine sinnvolle Eingabe!')
labelFehler.place(x=5, y=5, width=150, height=20)
# Button zum Schließen des Fensters
buttonOk = Button(master=tkFensterFehler, text='ok',
command=buttonOkClick)
buttonOk.place(x=5, y=30, width=150, height=20)
…
69
Messagebox-Fenster
from tkinter import *
# Ereignisbehandlung
def buttonBerechnenClick():
try:
# Übernahme der Daten
gewicht = float(entryGewicht.get())
groesse = float(entryGroesse.get())
# Verarbeitung der Daten
bmi = gewicht/(groesse*groesse)
bmiAnzeige = str(round(bmi*10)/10)
# Anzeige der Daten
labelBMI.config(text=bmiAnzeige)
except:
messagebox.showerror('Fehler', 'Keine sinnvolle Eingabe!')
Messagebox-Fenster
def buttonBeendenClick():
if messagebox.askyesno('Beenden', 'Soll das Programm wirklich beendet werden?'):
tkFenster.quit()
tkFenster.destroy()
…
70
Teil 5
GUI und Datenmodell
71
Datenverwaltung mit GUI-Objekten
# Ereignisbehandlung
def buttonWeiterClick():
stand = int(labelZahl.cget('text'))
stand = stand + 1
labelZahl.config(text=str(stand))
def buttonZurueckClick():
stand = int(labelZahl.cget('text'))
if stand > 0:
stand = stand - 1
labelZahl.config(text=str(stand))
def buttonNullClick():
stand = 0
labelZahl.config(text=str(stand))
...
# Label
labelZahl = Label(master=tkFenster, text='0', bg='gray', font=('Arial', 36))
labelZahl.place(x=5, y=5, width=160, height=80)
# Button
buttonWeiter = Button(master=tkFenster, text='weiter', bg='#D5E88F',
command=buttonWeiterClick)
…
72
Datenverwaltung mit GUI-Objekten
…
def buttonWeiterClick():
stand = int(labelZahl.cget('text'))
stand = stand + 1
labelZahl.config(text=str(stand))
...
stand = int(labelZahl.cget('text'))
unbefriedigende
Lösung:
Anwendungsdaten mit
GUI-Objekten
verwalten
{stand -> 0}
stand = stand + 1
{stand -> 1}
labelZahl.config(text=str(stand))
73
Datenverwaltung mit GUI-Objekten
Aufgabe:
Mit einem Programm soll die Anmeldung mit einem Passwort
simuliert werden.
Der Benutzer kann mit den Schaltflächen die Buchstaben A, B und
C eingeben. Wenn er/sie die Buchstabenkombination richtig
eingegeben hat, dann erhält er/sie eine positive, ansonsten eine
negative Rückmeldung.
Warum funktioniert bei dieser Anwendung der Ansatz, die Daten
zur Anwendung mit GUI-Objekten zu verwalten, nicht mehr?
74
Datenverwaltung mit globalen Variablen
# Datenmodell
stand = 0
# GUI - Ereignisbehandlung
def buttonWeiterClick():
global stand
stand = stand + 1
labelZahl.config(text=str(stand))
def buttonZurueckClick():
global stand
if stand > 0:
stand = stand - 1
labelZahl.config(text=str(stand))
def buttonNullClick():
global stand
stand = 0
labelZahl.config(text=str(stand))
…
labelZahl = Label(master=tkFenster, text=str(stand), bg='gray', font=('Arial', 36))
…
75
Datenverwaltung mit globalen Variablen
# Datenmodell
stand = 0
{stand -> 0}
# GUI - Ereignisbehandlung
def buttonWeiterClick():
global stand
stand = stand + 1
labelZahl.config(text=str(stand))
…
stand = stand + 1
wenig befriedigende
Lösung:
Anwendungsdaten
mit globalen Variablen
verwalten
labelZahl.config(text=str(stand))
{stand -> 1}
76
Datenverwalt. mit Datenmodellobjekten
# Datenmodellobjekt
from datenmodell import Zaehler
zaehler = Zaehler()
# GUI - Ereignisbehandlung
def buttonWeiterClick():
zaehler.weiter()
labelZahl.config(text=str(zaehler.stand))
…
zaehler.weiter()
gute Lösung:
Anwendungsdaten
mit separaten
Objekten verwalten
labelZahl.config(text=
str(zaehler.stand))
77
Datenverwalt. mit Datenmodellobjekten
class Zaehler(object):
def __init__(self):
self.stand = 0
def null(self):
self.stand = 0
def weiter(self):
self.stand = self.stand + 1
def zurueck(self):
if self.stand > 0:
self.stand = self.stand - 1
Bauplan für
Zaehler-Objekte
# Datenmodellobjekt
from datenmodell import Zaehler
zaehler = Zaehler()
Erzeugung e.
Zaehler-Objekts
# GUI - Ereignisbehandlung
def buttonWeiterClick():
zaehler.weiter()
labelZahl.config(text=str(zaehler.stand))
def buttonZurueckClick():
zaehler.zurueck()
labelZahl.config(text=str(zaehler.stand))
def buttonNullClick():
zaehler.null()
labelZahl.config(text=str(zaehler.stand))
# GUI-Objekte
from tkinter import *
…
labelZahl = Label(master=tkFenster,
text=str(zaehler.stand), …)
…
78
Übung
Aufgabe:
Mit einem Programm soll die Anmeldung mit einem Passwort
simuliert werden.
Der Benutzer kann mit den Schaltflächen die Buchstaben A, B und
C eingeben. Wenn er/sie die Buchstabenkombination richtig
eingegeben hat, dann erhält er/sie eine positive, ansonsten eine
negative Rückmeldung.
Benutze das Datenmodell und das Programmgerüst auf www.infschule.de, um die gezeigte GUI zu entwickeln.
79
Teil 6
Miniprojekte
80
Vorgehensweise
Schritt 1: Entwurf zur Benutzeroberfläche
Überlege dir zunächst, was die Benutzeroberfläche alles leisten soll: In welcher Weise soll sie
den Benutzer informieren? In welcher Weise soll der Benutzer selbst agieren können?
Entwickle (am besten auf Papier) einen ersten Entwurf für eine Benutzersoberfläche, die das
Gewünschte leistet.
Schritt 2: Struktur der Benutzeroberfläche
Erzeuge mit Hilfe geeigneter Komponenten eine Benutzeroberfläche, die den Entwurf umsetzt.
Lass zunächst alle Details der Prozeduren, die bei bestimmten Ereignissen ausgeführt werden
sollen, weg. Das Programm sollte lauffähig sein, aber noch nicht in der gewünschten Weise
beim Eintreten der jeweiligen Ereignisse reagieren.
Schritt 3: Dynamik der Benutzeroberfläche
Bei etwas komplexeren Programmen solltest du zunächst ein eigenständiges Datenmodell
entwickeln und unabhängig von der Benutzeroberfläche testen. Implementiere jetzt die
Prozeduren zur Ereignisbearbeitung. Teste alle Funktionalitäten des Programms Mach das
Programm möglichst fehlertolerant.
Schritt 4: Layout der Benutzeroberfläche
Zum Abschluss kannst du das Layout der Benutzeroberfläche nochmal überarbeiten und nach
deinen Wünschen gestalten.
81
Miniprojekt - Merktest
Wie viele Tasteneingaben kann man sich merken, wenn jemand schnell eine Zeichenfolge
eintippt? Diese Frage soll mit einem Simulationsprogramm geklärt werden. Benutzer 1 klickt
eine Folge von Schaltflächen (z.B. mit den Beschriftungen A, B und C) an. Benutzer 2
versucht, sich diese Eingabefolge zu merken und anschließend (auf einem zweiten
entsprechenden Schaltflächenblock) zu rekonstruieren. Bei der Auswertung wird überprüft,
wie viele Zeichen vom Beginn an korrekt wiedergeben worden sind.
Entwickle ein benutzerfreundliches Programm zum Merktest.
82
Miniprojekt - Taschenrechner
Der Taschenrechner soll folgendermaßen funktionieren:
Der Benutzer / die Benutzerin kann einfache Rechenaufgaben wie z. B. 342*28= mit
geeigneten Schaltflächen (die den Tasten entsprechen) eintippen. Mit einer bestimmten
Schaltfläche kann man den Taschenrechner aktivieren, die Rechnung durchzuführen und das
Ergebnis im Display anzuzeigen.
Es soll ein Programm zur Simulation eines Taschenrechners entwickelt werden. Über eine
grafische Benutzeroberfläche soll der Benutzer / die Benutzerin die Aktionen ausführen
können. Das Programm soll selbstbeschreibend und fehlertolerant gestaltet werden.
Orientiere dich bei der Entwicklung an den im letzten Abschnitt aufgezeigten Schritten.
83
Miniprojekt - Ziegenproblem
Weißt du, worum es beim Ziegenproblem geht? Wenn nicht, dann lies dir die Problemstellung
bei Wikipedia durch.
Mit Hilfe eines Simulationsprogramms soll herausgefunden werden, ob es für den Kandidaten
günstiger ist, bei seiner ersten Wahl zu bleiben, oder umzuwählen.
Entwickle ein Programm zur Simulation des Ziegenproblemspiels. Über eine grafische
Benutzeroberfläche soll der Spieler / die Spielerin die Spielaktionen des Kandidaten
durchführen können. Die Aktionen des Moderators sollen vom Programm übernommen
werden. Das Programm soll selbstbeschreibend und fehlertolerant gestaltet werden.
Orientiere dich bei der Entwicklung an den im letzten Abschnitt aufgezeigten Schritten.