Der pack-Manager
Experimente mit dem pack-Manager
Der pack-Manager (bzw. Packer) bestimmt die Anordnung von GUI-Komponenten automatisiert unter Berücksichtigung von Vorgaben im Programm.
Einige der vielen verschiedenen Gestaltungsmöglichkeiten mit dem pack-Manager sollen hier anhand einfacher GUIs aufgezeigt werden.
Beispiel 1: Aufruf der pack-Methode
Die pack
-Methode wird hier ohne Parameter aufgerufen.
from tkinter import *
tkFenster = Tk()
label1 = Label(master=tkFenster, text="0", bg="red", fg="white")
label1.pack()
label2 = Label(master=tkFenster, text="1", bg="green", fg="black")
label2.pack()
label3 = Label(master=tkFenster, text="2", bg="blue", fg="white")
label3.pack()
label4 = Label(master=tkFenster, text="3", bg="yellow", fg="black")
label4.pack()
tkFenster.mainloop()
Das Programm erzeugt die folgende GUI:
Beachte, dass die Größe des Fensters hier vom pack-Manager bestimmt wird.
Die einzelnen GUI-Komponenten werden mit dem Aufruf der pack
-Methode
in das Gesamtlayout übernommen und dabei untereinander angeordnet.
Aufgabe 1
Ändere die Reihenfolge der Aufrufe der pack
-Methode.
Welche Auswirkung hat dies?
Beispiel 2: Seitenvorgaben
Beachte die Ergänzungen im Aufruf der pack
-Methode.
from tkinter import *
tkFenster = Tk()
label1 = Label(master=tkFenster, text="0", bg="red", fg="white")
label1.pack(side='left')
label2 = Label(master=tkFenster, text="1", bg="green", fg="black")
label2.pack(side='left')
label3 = Label(master=tkFenster, text="2", bg="blue", fg="white")
label3.pack(side='left')
label4 = Label(master=tkFenster, text="3", bg="yellow", fg="black")
label4.pack(side='left')
tkFenster.mainloop()
Das Programm erzeugt jetzt die folgende GUI:
Aufgabe 2
(a) Probiere auch folgende Varianten bei der Seitenfestlegung aus: side='right'
, side='top'
,
side='bottom'
.
(b) Welches Layout erhält man beim folgenden Programm?
from tkinter import *
tkFenster = Tk()
label1 = Label(master=tkFenster, text="0", bg="red", fg="white")
label1.pack(side='right')
label2 = Label(master=tkFenster, text="1", bg="green", fg="black")
label2.pack(side='left')
label3 = Label(master=tkFenster, text="2", bg="blue", fg="white")
label3.pack(side='right')
label4 = Label(master=tkFenster, text="3", bg="yellow", fg="black")
label4.pack(side='left')
tkFenster.mainloop()
(c) Experimentiere selbst mit den Seitenfestlegungen.
Beispiel 3: Breite und Höhe anpassen
Mit dem fill
-Attribut kann man Höhe und Breite einer GUI-Komponente an den
vorgegebenen Rahmen anpassen.
from tkinter import *
tkFenster = Tk()
label1 = Label(master=tkFenster, text="0", bg="red", fg="white")
label1.pack(side='top', fill='x')
label2 = Label(master=tkFenster, text="1", bg="green", fg="black")
label2.pack(side='right', fill='y')
label3 = Label(master=tkFenster, text="2", bg="blue", fg="white")
label3.pack(side='top', fill='both')
label4 = Label(master=tkFenster, text="3", bg="yellow", fg="black")
label4.pack(side='left')
tkFenster.mainloop()
Das Programm erzeugt die folgende GUI:
Beachte, dass die Breite des Fensters durch einen voreingestellten Wert bestimmt wird.
Aufgabe 3
(a) Welche Auswirkungen haben die Festlegungen fill='x'
, fill='y'
,
fill='both'
?
(b) Variiere manuell die Fenstergröße. Welche Auswirkungen hat dies auf die GUI?
(c) Führe selbst weitere Experimente durch.
Beispiel 4: Abstände zum Rand bzw. Nachbarn festlegen
Man kann auch einen Raum um eine GUI-Komponente festlegen.
from tkinter import *
tkFenster = Tk()
label1 = Label(master=tkFenster, text="0", bg="red", fg="white")
label1.pack(side='top', fill='x', padx='5')
label2 = Label(master=tkFenster, text="1", bg="green", fg="black")
label2.pack(side='top', fill='x', pady='5')
label3 = Label(master=tkFenster, text="2", bg="blue", fg="white")
label3.pack(side='top', fill='x')
label4 = Label(master=tkFenster, text="3", bg="yellow", fg="black")
label4.pack(side='top', fill='x', padx='5', pady='10')
tkFenster.mainloop()
Das Programm erzeugt die folgende GUI:
Aufgabe 4
Führe selbst weitere Experimente durch.
Beispiel 5: Rahmen nutzen
Zur weiteren Strukturierung einer grafischen Benutzeroberfläche benutzt man Rahmen.
from tkinter import *
tkFenster = Tk()
rahmen1 = Frame(master=tkFenster, bg='magenta')
rahmen1.pack(side='top', padx='5', pady='5')
rahmen2 = Frame(master=rahmen1, bg='cyan')
rahmen2.pack(side='left', padx='5', pady='5')
rahmen3 = Frame(master=rahmen1, bg='cyan')
rahmen3.pack(side='left', padx='5', pady='5')
rahmen4 = Frame(master=tkFenster, bg='magenta')
rahmen4.pack(side='top', padx='5', pady='5')
label1 = Label(master=rahmen2, text="0", bg="red", fg="white")
label1.pack(side='top', padx='5', pady='5')
label2 = Label(master=rahmen2, text="1", bg="green", fg="black")
label2.pack(side='top', padx='5', pady='5')
label3 = Label(master=rahmen3, text="2", bg="blue", fg="white")
label3.pack(side='left', padx='5', pady='5')
label4 = Label(master=rahmen3, text="3", bg="yellow", fg="black")
label4.pack(side='left', padx='5', pady='5')
label5 = Label(master=rahmen4, text="4", bg="white", fg="black")
label5.pack(side='left', padx='5', pady='5')
label6 = Label(master=rahmen4, text="5", bg="black", fg="white")
label6.pack(side='left', padx='5', pady='5')
tkFenster.mainloop()
Das Programm erzeugt die folgende GUI:
Rahmen werden durch Objekte der Klasse Frame
implementiert.
Rahmen bilden "Container" für GUI-Komponenten. Mit dem master
-Attribut
wird die Zugehörigkeit zu einem solchen "Container" festgelegt.
Hierdurch ergibt sich eine sog. Master-Slave-Hierarchie.
Aufgabe 5
Führe selbst weitere Experimente durch.
Beispiel 6: Eine komplexe grafische Benutzeroberfläche
Ziel ist es, die folgende grafische Benutzeroberfläche mit dem pack-Manager zu erzeugen.
Der folgende (noch unvollständige) Quelltext soll als Grundlage dienen.
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')
# Frames
frameEingaben = Frame(master=...)
frameZahl1 = Frame(master=..., bg='#FFCFC9')
frameZahl2 = Frame(master=..., bg='#FFCFC9')
frameBerechnen = Frame(master=..., bg='#FBD975')
frameAusgaben = Frame(master=...)
frameErgebnis = Frame(master=..., bg='#D5E88F')
#frameEingaben.pack(...)
#frameBerechnen.pack(...)
#frameAusgaben.pack(...)
#frameErgebnis.pack(...)
#frameZahl1.pack(...)
#frameZahl2.pack(...)
# Label mit Aufschrift Zahl 1
labelZahl1 = Label(master=..., bg='white', text='Zahl 1')
#labelZahl1.pack(...)
# Entry für Zahl 1
entryZahl1 = Entry(master=..., bg='white', width='8')
#entryZahl1.pack(...)
# Label mit Aufschrift Zahl 2
labelZahl2 = Label(master=..., bg='white', text='Zahl 2')
#labelZahl2.pack(...)
# Entry für Zahl 2
entryZahl2 = Entry(master=..., bg='white', width='8')
#entryZahl2.pack(...)
# Button zum Addieren
buttonPlus = Button(master=..., text='+', width='2', command=buttonPlusClick)
#buttonPlus.pack(...)
# Button zum Subtrahieren
buttonMinus = Button(master=..., text='-', width='2',command=buttonMinusClick)
#buttonMinus.pack(...)
# Button zum Multiplizieren
buttonMal = Button(master=..., text='*', width='2', command=buttonMalClick)
#buttonMal.pack(...)
# Button zum Dividieren ohne Rest
buttonDurch = Button(master=..., text=':', width='2', command=buttonDurchClick)
#buttonDurch.pack(...)
# Button zum Rest bei der Division
buttonRest = Button(master=..., text='%', width='2', command=buttonRestClick)
#buttonRest.pack(...)
# Label mit Aufschrift Ergebnis
labelAufschriftErgebnis = Label(master=..., bg='white', text='Ergebnis')
#labelAufschriftErgebnis.pack(...)
# Label für das Ergebnis
labelErgebnis = Label(master=..., bg='white', width='8', text='')
#labelErgebnis.pack(...)
# Aktivierung des Fensters
tkFenster.mainloop()
Aufgabe 6
(a) Entwickle zunächst die Master-Slave-Struktur zu den GUI-Komponenten. Stelle diese Struktur mit einem Baumdiagramm dar und implementiere sie im Programm.
(b) Ergänze anschließend die Attribute zu den Aufrufen der pack
-Methoden.
Zur Kontrolle: Hier findest du eine Lösung.
Zusammenfassung
Die Grobstruktur des Layouts wird durch die Master-Slave-Struktur der GUI-Komponenten festgelegt.
Der Packer ordnet die Slave-Komponenten jeweils innerhalb der zugehörigen Master-Komponenten an. Folgende Parameter können dabei gesetzt werden.
Parameter | Bedeutung |
---|---|
side | Seite der Master-Komponente, an die die GUI-Komponente gesetzt wird. Mögliche Werte: 'left', 'right', 'top', 'bottom'. |
padx, pady | Leerer Platz rechts und links bzw. ober- und unterhalb der GUI-Komponente |
fill | Die GUI-Komponente wird so vergrößert, dass sie den gesamten zur Verfügung stehenden Platz ausfüllt. Mögliche Werte: 'x', 'y', 'both'. |
anchor | siehe tkinter-Dokumentation |
expand | siehe tkinter-Dokumentation |