Der place-Manager
GUI-Komponenten platzieren
GUI-Komponenten lassen sich mit dem place-Manager pixelgenau im Anwendungsfenster platzieren. Betrachte hierzu die folgende grafische Benutzeroberfläche für einen einfachen Rechner.
Der Quelltext zur abgebildeten GUI ist hier aufgelistet.
Beachte, dass bei der Ereignisbehandlung derselbe Quellcode in ähnlicher Form mehrfach vorkommt. Solche Codeduplizierungen versucht man in der Regel zu vermeiden. Wir werden uns in Abschnitt Verarbeitung von Ereignissen mit diesem Problem auseinander setzen. Vorerst soll es nur um die Anordnung der GUI-Komponenten gehen.
from tkinter import *
def buttonPlusClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 + zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonMinusClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 - zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonMalClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 * zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonDurchClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 // zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonRestClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 % zahl2
labelErgebnis.config(text=str(ergebnis))
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
labelZahl1 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 1')
labelZahl1.place(x=10, y=10, width=70, height=20)
entryZahl1 = Entry(master=tkFenster, bg='white')
entryZahl1.place(x=10, y=40, width=70, height=20)
labelZahl2 = Label(master=tkFenster, bg='#FFCFC9', text='Zahl 2')
labelZahl2.place(x=120, y=10, width=70, height=20)
entryZahl2 = Entry(master=tkFenster, bg='white', width='8')
entryZahl2.place(x=120, y=40, width=70, height=20)
buttonPlus = Button(master=tkFenster, text='+', width='2', command=buttonPlusClick)
buttonPlus.place(x=5, y=75, width=30, height=30)
buttonMinus = Button(master=tkFenster, text='-', width='2', command=buttonMinusClick)
buttonMinus.place(x=45, y=75, width=30, height=30)
buttonMal = Button(master=tkFenster, text='*', width='2', command=buttonMalClick)
buttonMal.place(x=85, y=75, width=30, height=30)
buttonDurch = Button(master=tkFenster, text=':', width='2', command=buttonDurchClick)
buttonDurch.place(x=125, y=75, width=30, height=30)
buttonRest = Button(master=tkFenster, text='%', width='2', command=buttonRestClick)
buttonRest.place(x=165, y=75, width=30, height=30)
labelAufschriftErgebnis = Label(master=tkFenster, bg='#D5E88F', text='Ergebnis')
labelAufschriftErgebnis.place(x=65, y=120, width=70, height=20)
labelErgebnis = Label(master=tkFenster, bg='white', width='8', text='')
labelErgebnis.place(x=65, y=150, width=70, height=20)
tkFenster.mainloop()
Im Quelltext sieht man, wie die einzelnen GUI-Komponenten hier platziert werden. Mit Hilfe der place
-Methode werden jeder GUI-Komponente Platz und Ausmaße zugeordnet. So legt z.B. die Anweisung labelAufschriftErgebnis.place(x=65, y=120, width=70, height=20)
fest, dass die GUI-Komponente zum GUI-Objekt labelAufschriftErgebnis
mit der linken oberen Ecke an die Position x=65, y=120
in einem zum Fenster gehörenden Koordinatensystem gesetzt wird. Zusätzlich wird die Breite und Höhe der GUI-Komponente festgelegt.
Folgende Parameter können beim Platzieren der GUI-Komponenten benutzt werden.
Parameter | Bedeutung |
---|
x, y | Position der GUI-Komponente im zugehörigen Koordinatensystem. |
width, height | Breite und Höhe der GUI-Komponente. |
Beachte, dass es bei komplexeren Benutzeroberflächen recht mühsam ist, alle Koordinaten und Ausmaße der GUI-Komponenten zu bestimmen.
Rahmen benutzen
Zusätzlich eingeführte Rahmen helfen oft bei der Strukturierung einer grafischen Benutzeroberfläche. Wir verdeutlichen dies anhand der etwas veränderten GUI für den einfachen Rechner.
Die Anordnung der GUI-Komponenten wird hier mit Hilfe von Rahmen festgelegt.
Implementiert werden solche Rahmen durch Objekte der Klasse Frame
dargestellt.
from tkinter import *
def buttonPlusClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 + zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonMinusClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 - zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonMalClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 * zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonDurchClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 // zahl2
labelErgebnis.config(text=str(ergebnis))
def buttonRestClick():
zahl1 = int(entryZahl1.get())
zahl2 = int(entryZahl2.get())
ergebnis = zahl1 % zahl2
labelErgebnis.config(text=str(ergebnis))
tkFenster = Tk()
tkFenster.title('Rechner')
tkFenster.geometry('200x180')
frameZahl1 = Frame(master=tkFenster, bg='#FFCFC9')
frameZahl1.place(x=5, y=5, width=80, height=60)
frameZahl2 = Frame(master=tkFenster, bg='#FFCFC9')
frameZahl2.place(x=115, y=5, width=80, height=60)
frameBerechnen = Frame(master=tkFenster, bg='#FBD975')
frameBerechnen.place(x=0, y=70, width=200, height=40)
frameErgebnis = Frame(master=tkFenster, bg='#D5E88F')
frameErgebnis.place(x=60, y=115, width=80, height=60)
labelZahl1 = Label(master=frameZahl1, bg='white', text='Zahl 1')
labelZahl1.place(x=5, y=5, width=70, height=20)
entryZahl1 = Entry(master=frameZahl1, bg='white')
entryZahl1.place(x=5, y=35, width=70, height=20)
labelZahl2 = Label(master=frameZahl2, bg='white', text='Zahl 2')
labelZahl2.place(x=5, y=5, width=70, height=20)
entryZahl2 = Entry(master=frameZahl2, bg='white', width='8')
entryZahl2.place(x=5, y=35, width=70, height=20)
buttonPlus = Button(master=frameBerechnen, text='+', width='2', command=buttonPlusClick)
buttonPlus.place(x=5, y=5, width=30, height=30)
buttonMinus = Button(master=frameBerechnen, text='-', width='2', command=buttonMinusClick)
buttonMinus.place(x=45, y=5, width=30, height=30)
buttonMal = Button(master=frameBerechnen, text='*', width='2', command=buttonMalClick)
buttonMal.place(x=85, y=5, width=30, height=30)
buttonDurch = Button(master=frameBerechnen, text=':', width='2', command=buttonDurchClick)
buttonDurch.place(x=125, y=5, width=30, height=30)
buttonRest = Button(master=frameBerechnen, text='%', width='2', command=buttonRestClick)
buttonRest.place(x=165, y=5, width=30, height=30)
labelAufschriftErgebnis = Label(master=frameErgebnis, bg='white', text='Ergebnis')
labelAufschriftErgebnis.place(x=5, y=5, width=70, height=20)
labelErgebnis = Label(master=frameErgebnis, bg='white', width='8', text='')
labelErgebnis.place(x=5, y=35, width=70, height=20)
tkFenster.mainloop()
Die Rahmen bilden eine Art "Container" für GUI-Komponenten. Mit dem master
-Attribut wird die Zugehörigkeit zu einem solchen "Container" festgelegt. Es ergibt sich eine Master-Slave-Hierarchie, die in der folgenden Abbildung exemplarisch für einige GUI-Komponenten dargestellt ist.
Man erhält erhält hier also folgende Komponenten-Verschachtelung:
tkFenster
ist master
von frameErgebnis
.frameErgebnis
ist master
von labelAufschriftErgebnis
.
Die Container-Objekte der Klassen Frame
legen genau wie Fenster-Objekte der Klasse Tk
Pixelkoordinatensysteme fest, mit deren Hilfe die umfassten Objekte genau platziert werden.
Die folgende Abbildung verdeutlicht exemplarisch diese Koordinatensysteme.
Aufgabe 1
Experimentiere mit den Rahmen. Verschiebe hierzu im Programm die Rahmen an eine andere Stelle auf dem Bildschirm. Verschiebe auch die Komponenten innerhalb eines Rahmens.
Rahmen übereinander legen
Platziert man in Python mehrere Rahmen an genau der gleichen Stelle, so liegen diese Rahmen übereinander und nur der zuletzt erzeugte Rahmen ist tatsächlich zu sehen. Mit der lift
-Methode können Rahmen in den Vordergrund gehoben werden. Das folgende Beispiel soll demonstrieren, wie diese lift
-Methode funktioniert.
from tkinter import *
def Button_Click_Deutsch():
frameDeutsch.lift()
def Button_Click_Englisch():
frameEnglisch.lift()
def Button_Click_Italienisch():
frameItalienisch.lift()
def Button_Click_Spanisch():
frameSpanisch.lift()
def Button_Click_Reset():
frameStart.lift()
tkFenster = Tk()
tkFenster.title('Frames liften')
tkFenster.geometry('400x225')
frameStart = Frame(master=tkFenster)
frameStart.place(x=0, y=20, width=400, height=180)
frameDeutsch = Frame(master=tkFenster, bg='red')
frameDeutsch.place(x=5, y=25, width=375, height=155)
frameEnglisch = Frame(master=tkFenster, bg='blue')
frameEnglisch.place(x=10, y=30, width=375, height=155)
frameItalienisch = Frame(master=tkFenster, bg='green')
frameItalienisch.place(x=15, y=35, width=375, height=155)
frameSpanisch = Frame(master=tkFenster, bg='orange')
frameSpanisch.place(x=20, y=40, width=375, height=155)
labelStart = Label(master = frameStart, text = 'Wähle eine Sprache!', font = ("Arial", 18))
labelStart.place(x=80, y=80)
frameStart.lift()
labelDeutsch = Label(master = frameDeutsch, text = 'Informatik', font = ("Arial", 18))
labelDeutsch.place(x=120, y=60)
labelEnglisch = Label(master = frameEnglisch, text = 'Informatics', font = ("Arial", 18))
labelEnglisch.place(x=120, y=60)
labelItalienisch = Label(master = frameItalienisch, text = 'Informatica', font = ("Arial", 18))
labelItalienisch.place(x=120, y=60)
labelSpanisch = Label(master = frameSpanisch, text = 'Informática', font = ("Arial", 18))
labelSpanisch.place(x=120, y=60)
buttonDeutsch = Button(master = tkFenster, text = 'Deutsch', fg = 'red', command = Button_Click_Deutsch)
buttonDeutsch.place(x=0, y=0, width=100, height=20)
buttonEnglisch = Button(master = tkFenster, text = 'Englisch', fg = 'blue', command = Button_Click_Englisch)
buttonEnglisch.place(x=100, y=0, width=100, height=20)
buttonItalienisch = Button(master = tkFenster, text = 'Italienisch', fg = 'green', command = Button_Click_Italienisch)
buttonItalienisch.place(x=200, y=0, width=100, height=20)
buttonSpanisch = Button(master = tkFenster, text = 'Spanisch', fg = 'orange', command = Button_Click_Spanisch)
buttonSpanisch.place(x=300, y=0, width=100, height=20)
buttonReset = Button(master = tkFenster, text = 'Zurücksetzen', command = Button_Click_Reset)
buttonReset.place(x=150 , y=200 , width=100, height=20)
tkFenster.mainloop()
Dieses Programm erzeugt zunächst die folgende GUI:
Klick man auf einen der Buttons, wird die lift
-Methode für den entsprechenden Rahmen ausgeführt und der Rahmen wird in den Vordergrund gehoben.
Aufgabe 2
Ändere das Programm aus dem Beispiel so ab, dass es nur noch einen Button gibt. Klickt man immer wieder auf den Button, so sollen die Rahmen in einer festgelegten Reihenfolge in den Vordergrund gelegt werden.