|
|
|
|
|
|
|
|
Geometrie-Manager (auch: Layout-Manager) lösen folgendes Problem: man hat eine Reihe von Widgets, beispielsweise 4 Buttons, 1 Eingabezeile und 1 Textwidget, und man möchte die Widgets in einer bestimmten Art und Weise auf dem Bildschirm in einem Fenster anordnen. Die Antwort auf dieses Problem heißt Geometrie-Manager, Beispiel:
Hier das Python-Skript (pack.py, Auszug!), in den hervorgehobenen Zeilen wird der Geometrie-Manager
pack()
aufgerufen:
root = Tk()
root.title('Chatten mit Python')
textfenster = Text(root,width=90)
textfenster.pack(fill=BOTH,expand=YES)
eingabe = Entry(root,width=60)
eingabe.pack(side=LEFT,fill=BOTH,expand=YES)
but1 = Button(root,text='Senden', command = senden)
but1.pack(side = LEFT,expand=NO)
but2 = Button(root,text='Verbinden', command = verbinde)
but2.pack(side = LEFT,expand=NO)
but3 = Button(root,text='Info', command = info)
but3.pack(side = LEFT,expand=NO)
but4 = Button(root,text='Beenden', command = ende)
but4.pack(side = LEFT,expand=NO)
Wie funktioniert der Geometrie-Manager? pack() versucht, die Widgets
in einem Rechteck anzuordnen, dabei bestimmt die Option side, wo das nächste Widget platziert wird. Die Voreinstellung ist TOP, fehlt also die Angabe von side wie in der folgenden Zeile
textfenster.pack(fill=BOTH,expand=YES)
so wird das Widget im Rechteck oben angeordnet. side kann die folgenden vier Werte annehmen: LEFT, RIGHT, TOP und BOTTOM (denke an die vier Himmelsrichtungen). Zu den anderen beiden Optionen:
fill kann die Werte Y, X, BOTH und NONE annehmen. Die Option bestimmt, ob und wie der Freiraum zwischen den einzelnen Widgets im Fenster gefüllt wird. Bei fill=NONE passiert gar nichts, bei fill=BOTH wird das Widget sowohl in x-Richtung (horizontal) bzw. in y-Richtung (vertikal) so vergrößert, dass es den zur Verfügung stehenden Platz im Rechteck ausfüllt.
expand kann die Werte YES bzw. NO annehmen. Die Option bestimmt, was beim Vergrößern des Fensters mit den Widgets passiert. Im Beispiel oben: wird das chat-Fenster vergrößert, so wachsen Text-Widget und Eingabezeile mit (expand=YES), während die Buttons so groß bleiben, wie sie sind (expand=NO).
Ein Geometrie-Manager wirkt entweder auf das Toplevel-Widget (im Beispiel oben: root) oder auf ein Frame-Widget. Ein Frame-Widget kann nicht direkt auf dem Bildschirm gezeichnet werden, es dient vielmehr als Behälter für andere Widgets. Beispiel (frame_02.py, Auszug!):
foben = Frame(root,width=500) foben.pack(expand=YES, fill=BOTH) textfenster = Text(foben,width=90,height=18) textfenster.pack(fill=BOTH,expand=YES) funten = Frame(root,width=500) funten.pack(side=BOTTOM,expand=YES, fill=BOTH) eingabe = Entry(funten,width=60) eingabe.pack(side=LEFT,fill=BOTH,expand=YES)
Im Beispiel gibt es zwei Frames (anschaulich: Bildschirm-Bereiche): Das Frame-Widget
foben enthält das Text-Widget. Unten ist das Frame-Widget funten mit dem Entry-Widget (und den Buttons). Im Aussehen unterscheidet sich das Skript frame_02.py nicht von dem Beispiel pack.py oben.
Neben dem pack-Layout-Manager bietet Tkinter noch zwei weitere Geometrie-Manager an:
place(): erlaubt eine Anordnung der Widgets in absoluten Koordinaten, anschaulich in Pixeln.
grid(): dieser Geometrie-Manager verwaltet ein Fenster wie eine Tabelle mit Zeilen (row) und Spalten (column), (schlechtes) Beispiel:but4.grid(row=1,column=4)grid- und des
pack-Layout-Manager nahe legt, ein verhängnisvoller Fehler! Deshalb hier die Faustregel:frame_grid.py)!
Der Mausklick auf einen Button ist ein Ereignis, das eine Aktion auslöst, Beispiel:
but1 = Button(root,text='Senden', command = senden)
Wird der Button but1 angeklickt, so wird die Aktion senden ausgelöst, mit dem Button ist also eine Aktion verknüpft. Nun will man bestimmte Aktionen
auch mit bestimmten Tastenkombinationen verbinden, beispielsweise die Tastenkombinationen ALT + F4 zum Beenden des Programms. Diese Aktion ist in Tkinter schon per Voreinstellung an die Tastenkombinationen ALT + F4 gebunden, aber will man beispielsweise den Inhalt einer Eingabezeile beim Drücken auf die <Return>-Taste auslesen (mit Hilfe der get()-Methode), so muss man die <Return>-Taste an die Eingabezeile binden, Beispiel (aus dem Skript bind.py):
eingabe = Entry(root,width=60)
## . . .
eingabe.bind('<Return>',callback)
eingabe.bind('<F1>',callback)
Der Methode callback wird über einen Parameter mitgeteilt, dass sie auf ein Ereignis (=Event) reagieren soll. Tritt das betreffende Ereignis ein, so wird die Ereignisbehandlungs-Routine callback (=Event-Handler) ausgeführt:
def callback(event):
tkMessageBox.showinfo('Senden','May be later!')
Binding sorgt also bei einem Widget für die Verknüpfung einer Methode (die Ereignisbehandlungs-Routine callback) mit einem Ereignis (<Return>-Taste gedrückt). Alternativ zu <Return> kann man verwenden:
eingabe.bind('<Alt-y>',callback) ## Achtung: kleines y
eingabe.bind('<Control-E>',callback) ## Achtung: GROSSES E
eingabe.bind('<Key-Escape>',callback)
## Die Pfeiltasten:
textfenster.bind('<Shift-Up>',callback)
textfenster.bind('<Shift-Down>',callback)
## Jetzt die rechte Maustaste:
textfenster.bind('<Button-3>',callback)
Die letzten Beispiele beziehen sich auf das Text-Widget, die Informationen zu der korrekten Schreibweise der Tasten- und Mauskombinationen findet man in der Dokumentation!
<<<pack() vertraut! Überprüfe vor allem: was passiert, wenn man das side-Argument verändert (statt LEFT RIGHT oder BOTTOM). Benutze für deine Versuche in IDLE das Skript pack.py, verändere es vorsichtig und speichere es unter einem anderen Namen ab.
pack.py so um, das bei den Buttons der grid()-Manager benutzt wird, etwa so:
but1 = Button(root,text='Senden', command = senden) but1.grid(row=1,column=1) but2 = Button(root,text='Verbinden', command = verbinde) but2.grid(row=1,column=2) but3 = Button(root,text='Info', command = info) but3.grid(row=1,column=3) but4 = Button(root,text='Beenden', command = ende) but4.grid(row=1,column=4)Abspeichern (unter einem anderen Namen!) und ab geht's in die Katastrophe! Vergleiche deine Bemühungen mit dem Skript
frame_grid.py, wo liegt der Unterschied? Welche Schlußfolgerung kann man daraus ziehen?
pack.py Frames ein und vergleiche deine Bemühungen mit den Skripten frame_01.py und frame_02.py. Experimentiere auch hier mit dem Geometrie-Manager pack().
callback-Methode weitere Methoden, und binde sie an irgendwelche Widgets und Tastenkombinationen! Geht auch die linke Maus-Taste? Oder beide Maus-Tasten? Wie? Vergleiche deine Ergebnisse mit dem Skript bind.py.