Python - Grafische Oberflächen mit TKinter erstellen
Grafische Benutzeroberflächen... Graphical User Interface (GUI) sind eine Schnittstelle zwischen Mensch und Maschine. steuern die Eingabe und Ausgabe von Daten. können mit Hilfe von Python und der Bibliothek Tkinter erstellt werden. Die Code-Dateien besitzen die Endung.pyw. Python - Programmierung, 28.10.10 Seite 2
entwickeln Wie soll die Benutzeroberfläche aussehen? Corporate Desgin des Auftraggebers. Styleguides. Barrierefreiheit. Was erwartet der Benutzer? Was soll die Benutzeroberfläche tun? Welche Arbeitsabläufe sollen in welcher Reihenfolge abgebildet werden? Welches Vorwissen benötigt der Benutzer um die Abläufe korrekt zu erledigen? Python - Programmierung, 28.10.10 Seite 3
Pakete in Python Tkinter ist in der Standardinstallation von Python implementiert und arbeitet mit Tck/Tk-Steuerelementen. wxwindows (wxwidget) ist eine GUI-Klasse, geschrieben in C++. PyQT stellt QT-Bibliotheken für Python zur Verfügung. Informationen zu den Paketen finden Sie unter http://docs.python.org/py3k/faq/gui.html. Python - Programmierung, 28.10.10 Seite 4
bestehen aus... einem Fenster (window) und einer beliebige Anzahl von Steuerelementen (Widget). Python - Programmierung, 28.10.10 Seite 5
Fenster (window)... hat immer eine rechteckige Form. wird durch einen Rahmen begrenzt. hat eine Titelleiste, die Auskunft über die Funktion des Fensters gibt. können Container und Controls (Steuerelemente) enthalten. Python - Programmierung, 28.10.10 Seite 6
Widget... ist aus den Wörtern Window und Gadget gebildet. sind Steuerelemente (Controls). sind grafische Elemente, die in einem Fenster abgelegt werden. können nur in einem Fenster oder Container existieren. Python - Programmierung, 28.10.10 Seite 7
Beispiele Textfelder ermöglichen die Eingabe von Text. Label (Beschriftungsfelder) zeigen Text als Information für Benutzer an. Schaltflächen starten Aktionen. Listenfelder, Kontrollkästchen sowie Optionsfelder ermöglichen eine Auswahl von Elementen. Python - Programmierung, 28.10.10 Seite 8
mit Tkinter erstellen «from tkinter import *» root = Tk() caption = "Herzlich Willkommen" bezeichnungsfeld = Label(root, text = caption) bezeichnungsfeld.pack() root.mainloop() Python - Programmierung, 28.10.10 Seite 9
Tkinter importieren «from tkinter import *» importiert alle Methoden vom Modul tkinter, ohne das die Methoden etc. im Programm mit dem Modulnamen verbunden werden müssen. Informationen zu Tkinter finden Sie auf folgenden Web-Seiten: http://docs.python.org/py3k/library/tk.html http://www.pythonware.com/library/tkinter/ introduction/index.htm http://infohost.nmt.edu/tcc/help/pubs/tkinter/ Python - Programmierung, 28.10.10 Seite 10
Wurzel -Fenster erzeugen «root = Tk()» erzeugt ein Top-Level-Fenster. Das Fenster ist Mutter aller anderen Fenster. Das oberste Fenster wird meist «root» genannt. Die Variable «root» verweist auf eine Instanz der Klasse «Tk()». Python - Programmierung, 28.10.10 Seite 11
Nachrichten-Schleife starten «root.mainloop()» erzeugt einen Wachhund für Ereignisse. Die Schleife wartet auf Ereignisse, die durch Eingaben oder Aktionen des Benutzers ausgelöst werden. Durch Zerstörung des Fensters wird die Nachrichtenschleife beendet. Zum Beispiel: Die Schließen-Schaltfläche wird gedrückt und das Fenster automatisch geschlossen. Das Fenster wird zerstört. Die dazugehörige Nachrichten-Schleife wird beendet. Python - Programmierung, 28.10.10 Seite 12
Container und Widget definieren class Application(Frame): def init (self, master=none): Frame. init (self, master) self.pack() self.createwidgets() def createwidgets(self): ausgabetext = "Herzlich Willkommen" self.lblhallo = self.createlabel(ausgabetext) self.lblhallo.pack() def createlabel(self, caption): bezeichnungsfeld = Label(root, text = caption) return bezeichnungsfeld Python - Programmierung, 28.10.10 Seite 13
und erstellen «from tkinter import *» root = Tk() app = Application(master=root) app.mainloop() Python - Programmierung, 28.10.10 Seite 14
Container... sind Behältnisse für andere Widgets. gruppieren Widgets, die zu einem Arbeitsablauf oder zu einer Aktion gehören. definieren ein Layout für Benutzeroberflächen. werden automatisch geschlossen, wenn das Eltern-Fenster geschlossen wird. Die Größe des Containers wird durch den Inhalt festgelegt. Python - Programmierung, 28.10.10 Seite 15
... erstellen «app = Application(master=root) app.mainloop()» class Application(Frame): def init (self, master=none): Frame. init (self, master) Python - Programmierung, 28.10.10 Seite 16
Basisklasse Frame... definiert einen rechteckigen Container. vererbt an die benutzerdefinierte Klasse «Application» Eigenschaften und Methoden. wird als Grundlage für die Erstellung eines Rahmens im Fenster «root» genutzt. Python - Programmierung, 28.10.10 Seite 17
Eltern-Kind (Master-Slave) - Beziehung root : Tk label : Label text : Entry container : Frame label : Label text : Entry button : Button Python - Programmierung, 28.10.10 Seite 18
Konstruktor... def init (self, master=none): Frame. init (self, master) self.pack() self.createwidgets() ruft den Konstruktor der Basisklasse auf. wird das Eltern-Fenster und die aufrufende Instanz übergeben. ordnet die Widgets mit Hilfe des Geometry-Managers an. erstellt die Widgets, die im Container vorhanden sind. Python - Programmierung, 28.10.10 Seite 19
Widget... werden immer in einem Container oder Fenster abgelegt. interagieren mit dem Benutzer. stellen Informationen für den Benutzer übersichtlich dar. gestalten das Aussehen des Containers. können Events auslösen. Python - Programmierung, 28.10.10 Seite 20
Beispiele Bezeichnungsfelder zeigen Informationen für den Benutzer an. Mit Hilfe der Tastatur werden Daten in Textfelder eingegeben. Mit Hilfe von Listenfeldern, Optionsfeldern oder Kontrollkästchen kann der Nutzer Daten mit der Maus auswählen. Schaltflächen starten Aktionen. Python - Programmierung, 28.10.10 Seite 21
in TKinter http://www.scripps.edu/~sanner/python/inputform/ tkinterwidgets.html http://www.pythonware.com/library/tkinter/introduction/ tkinterreference.htm Python - Programmierung, 28.10.10 Seite 22
Bezeichnungsfeld... bezeichnungsfeld = Label(root, text = caption) bezeichnungsfeld.pack() enthält Text, der vom Nutzer der Oberfläche nicht verändert werden kann. bietet Hilfen zum Ausfüllen von Textfeldern, etc. zeigen mehrzeiligen, unveränderbaren Text an. steht häufig links von einem Widget oder oberhalb eines Widgets. Python - Programmierung, 28.10.10 Seite 23
erzeugen Durch Aufruf der passenden Klasse wird ein Widget erzeugt. Zum Beispiel «Label(root, text = caption)» erzeugt ein Bezeichnungsfeld. Dem Kontruktor wird... der Container, in dem das Widget liegt oder das Eltern-Fenster übergeben. Python - Programmierung, 28.10.10 Seite 24
Attribute des Bezeichnungsfeldes «text = "Ausgabetext"» definiert den angezeigten Text. «bg = 'white'» oder «background = '#fff'» definiert eine Hintergrundfarbe. «fg = 'black'» oder «foreground = '#000000'» definiert die Schriftfarbe (Vordergrundfarbe). «font = ('Arial', '22', 'bold')» definiert die Schriftart. Python - Programmierung, 28.10.10 Seite 25
festlegen mit Hilfe von Schlüsselwort-Argumenten bei der Generierung eines Widgets. Beispiel: «bezeichnungsfeld = Label(root, text = caption)». mit Hilfe der Instanzvariablen und einem Schlüsselwert. Beispiel: «bezeichnungsfeld['text'] = caption» Python - Programmierung, 28.10.10 Seite 26
Farb-Attribute... nutzen RGB (red, green, blue). Das Farbsystem RGB bietet für die Farben Rot, Grün, Blau 256 Helligkeitsstufen an. Die Farbe weiß hat eine Rot-Anteil von 255, einen Grün-Anteil von 255 und einen Blau-Anteil von 255. Um so mehr sich eine Farbe dem Wert 255 annährt, um so heller ist sie. Python - Programmierung, 28.10.10 Seite 27
Grundfarben in Python «fg = 'black'» «fg = 'white'» «fg = 'red'» «fg = 'green'» «fg = 'blue'» «fg = 'cyan'» «fg = 'magenta'» «fg = 'yellow'» Python - Programmierung, 28.10.10 Seite 28
und als Hexidezimalzahl codiert. Farben werden als Hexadezimalzahlen (0-9, A-F) definiert. Beispiele: rot #F00 #FF0000 grün #0F0 #00FF00 blau #00F #0000FF weiß #FFF #FFFFFF schwarz #000 #000000 LUH-Blau #3d72b8 Grau #808080 Python - Programmierung, 28.10.10 Seite 29
Textfeld... self.txtzeile = Entry(self) self.txtzeile.pack() Eingabe von Text oder Anzeige von veränderbaren Text. kann mehrzeilig sein. Python - Programmierung, 28.10.10 Seite 30
erzeugen «self.txtzeile = Entry(self)» erzeugt ein einzeiliges Textfeld. «self.txtdokument = Text(self)» erzeugt ein mehrzeiliges Textfeld. Dem Kontruktor wird... der Container übergeben, in dem das Widget liegt. können in Abhängigkeit des gewählten Widget verschiedene Attribute übergeben werden. Python - Programmierung, 28.10.10 Seite 31
Attribute des Textfeldes «bg = 'white'» oder «background = '#fff'» definiert eine Hintergrundfarbe. «fg = 'black'» oder «foreground = '#000000'» definiert die Schriftfarbe (Vordergrundfarbe). «font = ('Arial', '22', 'bold')» definiert die Schriftart. Python - Programmierung, 28.10.10 Seite 32
anordnen... self.txtzeile.pack() Mit Hilfe der Methode «.pack()» werden die Widgets in Abhängigkeit der Seiten des Containers angeordnet. Das Widget wird sichtbar. Die Methode ruft einen so genannten Geometry Manager auf. Python - Programmierung, 28.10.10 Seite 33
Geometry Manager... zeigt Widgets in einen Container an. ordnet Widgets exakt auf ihren Eltern-Widget an. positioniert Widgets in einem Fenster oder Container. Python - Programmierung, 28.10.10 Seite 34
bietet folgende Möglichkeiten «.pack()» platziert ein Widget in Bezug auf die vorhandenen Widgets in einem Container. Als Bezugsgrößen werden die Seiten des Containers genutzt. «.grid()» erstellt ein unsichtbares Raster in Form von Zeilen und Spalten. «.place()» nutzt absolute Positionsangaben. In einem Container sollte jeweils nur eine Methode für die Platzierung von Widgets genutzt werden. Python - Programmierung, 28.10.10 Seite 35
Pack-Manager «self.pack() self.zeichenflaeche.pack(fill=x) self.label.pack(side=left) self.txtformel.pack(side=left)» self.cmdzeichnen.pack(side=right,pady=10,padx=10) Python - Programmierung, 28.10.10 Seite 36
Nutzungsmöglichkeiten Das Widget füllt den Container vollständig aus. Die Widgets werden in einer Reihe angeordnet. Die Widgets werden als Stapel angeordnet. Python - Programmierung, 28.10.10 Seite 37
Widgets stapeln «class Application(Frame): def createwidget(self): self.button01 = Button(self) self.button01.pack() self.button02 = Button(self) self.button02.pack() self.button03 = Button(self) self.button03.pack()» Python - Programmierung, 28.10.10 Seite 38
Container vollständig ausfüllen «from tkinter import * class clszeichnen(frame): def init (self, parent = None): Frame. init (self, parent) self.pack(fill=both, expand=1) self.photo = PhotoImage(file="Penguins.gif")» self.zeichenflaeche = Canvas(self, bg='white') self.item = self.zeichenflaeche.create_image(0,0, anchor=nw, image=self.photo) self.zeichenflaeche.pack(fill=both, expand=1) Python - Programmierung, 28.10.10 Seite 39
Atribut fill Durch Wertzuweisung an das Attribut «.pack(fill=)» kann das Widget einen Container vollständig abdecken. Folgende Einstellungsmöglichkeiten sind vorhanden: «.pack(fill=x)». Horizontale Abdeckung des Containers. «.pack(fill=y)». Vertikale Abdeckung des Containers. «.pack(fill=both)». Vollständige Abdeckung des Containers. «.pack(expand=1)» passt die Größe des Widgets an, wenn sich die Größe des Anwendungsfensters verändert. Python - Programmierung, 28.10.10 Seite 40
An eine Seite des Containers andocken self.txtformel.pack(side=left) self.cmdzeichnen.pack(side=right,pady=10,padx=10) Mit Hilfe der Option «.pack(side)» wird das Widget an eine Seite ( «LEFT», «RIGHT», «TOP», «BOTTOM», «CENTER» ) des Containers gebunden. Falls alle Widgets nebeneinander angeordnet werden sollen, müssen alle Widgets die gleiche Seitenangabe besitzen. «.pack(padx)» oder «.pack(pady)» definiert einen Abstand zwischen den Widgets. Python - Programmierung, 28.10.10 Seite 41
Grid-Manager «self.lblhallo.grid(row=0, padx=10, pady=10) self.lblzahllinks.grid(column=0, row=1)» self.txtzahllinks.grid(column=1, row=1, columnspan=2, padx=10, pady=10) Python - Programmierung, 28.10.10 Seite 42
Nutzungsmöglichkeiten Die Widgets werden mit Hilfe eines Raster auf den Eltern- Element abgelegt. Der Container wird in Zeilen und Spalten eingeteilt. Innerhalb dieser definierten Tabelle werden die Widgets abgelegt. Python - Programmierung, 28.10.10 Seite 43
Attribute «.grid(row=0)». In welcher Zeile befindet sich das Widget? «.grid(column=0)». In welcher Spalte befindet sich das Widget? Der Index 0 bezeichnet die erste Zeile oder Spalte einer Tabelle. Falls kein Index angegeben wird, wird die erste freie Zeile oder Spalte genutzt. Mit Hilfe von «.grid(rowspan=2)» oder «.grid(columnspan=2)» können Zeilen oder Spalten verbunden werden. «.grid(column=1, row = 1, sticky = NW)». In Abhängigkeit der Himmelsrichtungen können die Widgets in einer Zelle positioniert werden. Python - Programmierung, 28.10.10 Seite 44
Schaltflächen (Button)... button = Button(self) button['text'] = 'Schließen' button['width'] = 30 button['font'] = ('Arial',18, 'bold') starten eine Aktion mit Hilfe eines Mausklicks. haben eine Beschriftung, die die hinterlegte Aktion beschreibt. Häufig wird die Aktion mit Hilfe eines Verbs beschrieben. In diesem Beispiel wird mit Hilfe des Buttons das Fenster geschlossen. Python - Programmierung, 28.10.10 Seite 45
Welche Aktion wird gestartet? «button = Button(self) self.button.bind("<button-1>", self.button_click)» def button_click(self, event): self.myparent.destroy() Mit Hilfe der Methode «.bind()» wird eine Prozedur gestartet, die die Aktion in der Sprache Python beschreibt. Prozeduren, die auf ein Ereignis reagieren, werden als Event- Handler bezeichnet. Python - Programmierung, 28.10.10 Seite 46
Ereignis (Event)... tritt immer in Verbindung mit einem Fenster, Container oder Widget auf. wird durch die Maus, Tastatur oder dem Neuzeichnen des Fensters ausgelöst. ist eine Reaktion auf eine Aktion, ausgelöst durch den Benutzer. Auf Ereignisse kann reagiert werden, muss aber nicht. Python - Programmierung, 28.10.10 Seite 47
Event-Handler... beschreibt die Reaktion auf ein Ereignis. muss nicht für jedes mögliche eintretende Ereignis geschrieben werden. bestehen wie benutzerdefinierte Prozeduren in Python aus einem Prozedurkopf und rumpf. haben folgende Argumente: «self» für das aktuelle Objekt in einer Klasse. Objekt «event», welches das Ereignis beschreibt. Python - Programmierung, 28.10.10 Seite 48
Namen des Event-Handler Der Name sollte die Aktion beschreiben. Der Name kann aus dem Namen des Auslöser sowie der Event-Bezeichnung zusammengesetzt werden. Der Name beachtet die Regeln zur Namensbildung für Prozeduren in Python. Python - Programmierung, 28.10.10 Seite 49
Maus-Ereignisse «"<Button-1>"». Die linke Maustaste ist gedrückt. «"<Enter>"». Der Mauszeiger wird in ein Widget hinein bewegt. «"<Leave>"». Der Mauszeiger verlässt ein Widget. «"<FocusIn>"». Das Widget bekommt den Fokus. «"<FocusOut>"». Das Widget verliert den Fokus. Python - Programmierung, 28.10.10 Seite 50
Beispiele «# Auf Mausklick wird das Eltern-Fenster zerstört def button_click(self, event): self.myparent.destroy() # Selbst definierter Event-Handler zum Zeichnen def zeichnen(self, event): strformel = self.txtformel.get() for zaehler in range(4000): x = zaehler / 200.0-10 if strformel!= "": formel = eval(strformel) Python - Programmierung, 28.10.10 Seite 51
Attribute von Maus-Ereignissen «def button_click(self, event): # Welche Instanz hat das Event ausgelöst? print("auslöser: ", event.widget) # Wo befindet sich der Mauszeiger? print("an der Position: ", event.x, " - ", event.y)» self.myparent.destroy() Python - Programmierung, 28.10.10 Seite 52
Tastatur-Ereignisse «"<Key>"». Der Benutzer drückt eine Taste. «"<Return>"». Der Benutzer drückt die Return -Taste. Python - Programmierung, 28.10.10 Seite 53
Beispiele «def proofkey(self, event): asciicode = ord(event.char)» if (asciicode < 48) or (asciicode > 57): return "break" def Addition(self, event): summe = zahllinks + zahlrechts self.txtergebnis.delete(0, END) self.txtergebnis.insert(0, str(summe)) Python - Programmierung, 28.10.10 Seite 54
Tastatur-Ereignisse «event.char». Welche Tastatur ist gedrückt? «event.keycode». Keycode der gedrückten Taste. Python - Programmierung, 28.10.10 Seite 55
Event-Handler abbrechen «def proofkey(self, event): asciicode = ord(event.char)» if (asciicode < 48) or (asciicode > 57): return "break" Mit Hilfe von «return 'break'» wird ein Ereignis abgebrochen. In diesem Beispiel wird, falls keine Zahl gedrückt wurde, das Ereignis abgebrochen und das Zeichen nicht im Textfeld angezeigt. Python - Programmierung, 28.10.10 Seite 56
Bindung an eine Instanz «self.button.bind("<button-1>", self.button_click)». Die Methode bindet ein Ereignis «"<Button-1>"» an einen Event- Handler «self.button_click». Der Methode wird der Name des Event-Handlers übergeben. Die runden Klammern für die Argumentliste werden nicht benötigt. Es können mehr als ein Event-Handler an ein Ereignis gebunden werden. Python - Programmierung, 28.10.10 Seite 57
Abarbeitung von Ereignissen 1 2 3 4 Widget «.bind("event", handler)» Top-Level-Window «.bind("event", handler)» Widget-Class «.bind_class("event", handler)» Application «.bind_all("event", handler)» Python - Programmierung, 28.10.10 Seite 58
Command-Binding «self.button = Button(self, width=30, command=self.get_selecttext)». Die Bindung erfolgt über das Attribut «command». Nicht alle Widgets besitzen dieses Attribut. Sobald auf den Button geklickt wird, wird der Event-Handler «self.get_selecttext» ausgeführt. Dem aufgerufene Event-Handler «def get_selecttext(self):» wird nur das aktuelle Objekt übergeben. Python - Programmierung, 28.10.10 Seite 59