i

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:

Anwendungsfenster

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:

Anwendungsfenster

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:

Anwendungsfenster

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:

Anwendungsfenster

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:

Anwendungsfenster

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.

Anwendungsfenster

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.

Anwendungsfenster

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 Handbuch
expand siehe Handbuch

Suche

v
5.1.4.5.2
inf-schule.de/software/gui/entwicklung_tkinter/layout/pack

Rückmeldung geben