Python GUI tkinter Kontrollelemente
Willemers Informatik-Ecke
Layout Python-Kurs Zeichnen im Canvas

Weiterführende Themen Zwei Kontrollelemente haben Sie bereits kennengelernt: Den Button und das Label. Während das Label lediglich dazu dient, etwas anzuzeigen, ist der Button ein aktives Element.

Label

Wie jedes Kontrollelement braucht auch das Label als ersten Parameter das Elternfenster. Da einem Label der Inhalt meist bereits bei der Erstellung zugewiesen wird, kann man diesen auch dem Konstruktor übergeben.
anzeige = Label(Fenster, text = "Guten Tag")
Sie können einem Label aber auch nachträglich jederzeit einen anderen Text zukommen lassen. Dabei können Sie die Methode config verwenden:
anzeige.config(text="Guten Tag")
Sie können die Änderung auch über die rechteckigen Indexklammern erreichen wie bei einem Dictionary:
anzeige["text"] = "Guten Abend"

Button

Ein Button bedient ebenfalls die Ressource text wie ein Label. Die Hauptfunktionalität besteht allerdings darin, dass er gedrückt wird. Der Ressource command wird eine parameterlose Funktion zugewiesen, die aufgerufen wird, wenn jemand drückt.
def callbackFunktion():
    tuirgendwas()

Knopf = Button(elternFenster, 
        text = meldung,
        command = callbackFunktion)

Radiobutton

Radiobuttons treten immer im Rudel auf. Dabei kann immer nur einer der Buttons angewählt sein, so wie bei einem Radio immer nur ein Programm eingeschaltet ist. Ein Radiobutton hat darum drei entscheidende Ressourcen. Alle Radiobuttons mit einem gemeinsamen Elternfenster gehören zusammen. Die Ressource variable bestimmt die Variable, in der der Wert des Radiobutton abgelegt wird, der wiederum in der Ressource value festgelegt wird.
Radiobutton(ElternFenster, text="N3",  variable=sender, value=3)
Radiobutton(ElternFenster, text="ZDF", variable=sender, value=2)
Das folgende Programm erstellt ein kleines Fenster, in dem sich drei Radiobuttons befinden, über die der Fernsehsender ausgewählt werden kann.
from tkinter import *
ElternFenster = Tk()
sender = IntVar()  # tkinter Variablenklasse
sender.set(1)
Liste = [ ("ARD", 1), ("ZDF", 2), ("N3", 3), ("arte", 4) ]

def ZeigAuswahl():
    print(sender.get())

for name, nr in Liste:
    Radiobutton(ElternFenster, text=name, variable=sender,
                command=ZeigAuswahl, value=nr).pack()
mainloop()

Checkbox

Der Check in Checkbox deutet schon an, wofür sie gut ist. Man kann den Button mit einem Haken versehen. Alle Ja-Nein-Fragen können mit diesem Kontrollelement abgefragt werden.
info = IntVar()
Checkbutton(ElternFenster, text="beschriftung", variable=info)
print(info.get())

Eingabefeld Entry

Folgen Sie dem Link!

Listbox mit Scrollbar

Eine Listbox ohne Schiebebalken ist auf Dauer wenig sinnvoll, darum wird es hier im Paket erläutert. Im Gegensatz zu einigen Anderen grafischen Oberflächen wird die Listbox nicht als Kind-Widget in ein Scrollbar-Widget gesetzt. Tkinter betrachtet sie als eigenständige Widgets gleicher Ebene. So muss der Programmierer Listbox und Scrollbar nebeneinander anordnen. Im Beispiel wird dies durch zwei Pack-Aufrufe erledigt. Um ein Listbox-Element logisch mit einem Schiebebalken zu verknüpfen, muss dessen Callback-Ressource yscrollcommand auf die Scrollbar-Methode set() gelenkt werden. Anders herum muss die Ressource command des Schiebebalkens auf die Methode yview() der Listbox gelenkt werden.
from tkinter import *

fenster = Tk()
scrollbar = Scrollbar(fenster)
scrollbar.pack(side=RIGHT, fill=Y)
listbox = Listbox(fenster, yscrollcommand=scrollbar.set)
for i in range(1000):
    listbox.insert(END, str(i))
listbox.pack(side=LEFT, fill=BOTH)
scrollbar.config(command=listbox.yview)
mainloop()
Die Listbox wird über ihre Methode insert() mit Elementen gefüllt. Der zweite Parameter enthält den einzufügenden String, der erste Parameter gibtt die Position an, an der der String eingefügt werden soll. Der Wert tkinter.END befördert die Zeile an das Ende der Liste.

Es ist in der Regel sinnvoll, einen Frame um Listbox und Scrollbar zu legen. Damit ist ausgeschlossen, dass sich weitere Elemente, die man in das Fenster einbauen möchte, dazwischen mogeln.

listframe = tkinter.Frame(fenster)
scrollbar = tkinter.Scrollbar(listframe)
scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
listbox = tkinter.Listbox(listframe, yscrollcommand=scrollbar.set)
for i in range(1000):
    listbox.insert(tkinter.END, str(i))
listbox.pack(side=tkinter.LEFT, expand=True, fill=tkinter.BOTH)
scrollbar.config(command=listbox.yview)
listframe.pack(expand=True, fill=tkinter.X)

Combobox

Eine Combobox ist eine Kombination aus Eingabefeld und Liste. Dabei klappt die Liste erst aus, wenn man den Pfeil-Button am rechten Rand anklickt. Aus diesem Grund wird dieses Element auch in manchen GUIs Dropdownlist genannt.

Um die Klasse Combobx nutzen zu können, muss aus tkinter das Modul ttk importiert werden.

from tkinter import ttk
#...
ziffern = ["1", "2", "3", "4", "5", "6"]
combo = ttk.Combobox(frame, state="readonly", values=ziffern))
combo.current(0)

Methoden

Event

Das Programm kann daran teilhaben, wenn ein anderes Element der Liste ausgewählt wird. Dazu muss eine Event-Funktion mit dem Ereignis <<ComboboxSelected>> verknüpft werden.
from tkinter import ttk

def SelChanged(event):
    selection = combo.get()

ziffern = ["1", "2", "3", "4", "5", "6"]
combo = ttk.Combobox(frame, state="readonly", values=ziffern))
combo.bind("<<ComboboxSelected>>", SelChanged)

Menü

Ein einfaches Menü besteht aus einer Menüleiste, einem Dateimenü und einem Menüpunkt für Quit, der das Programm beendet und dazu die gleiche Callback-Funktion ende benutzt, die zuvor schon der Button eingesetzt hat.
MenueLeiste = Menu(Fenster)
DateiMenue = Menu(MenueLeiste, tearoff=0)
MenueLeiste.add_cascade(label="Datei", menu=DateiMenue)
DateiMenue.add_command(label="Quit", command=ende)
Fenster["menu"] = MenueLeiste
Soll noch ein Bearbeiten-Menü hinzukommen, müssen Sie Menu() aufrufen und als Elternfenster MenueLeiste verwenden. Soll dagegen im Dateimenü noch weitere Punkte auftreten, rufen Sie Menu() mit dem Elternfenster DateiMenue auf.

Anschließend müssen die Menübestandteile allerdings noch mit den add-Funktionen eingehängt werden. Dabei steht add_cascade für das kaskadierende Einhängen und add_command für das Einhängen eines Buttons. Mit der Funktion add_radiobutton können Sie sogar Radio-Buttons in einem Menü verwenden. % TODO Folgendes Menue noch aendern:

AuswahlMenue = Menu(MenueLeiste, tearoff=0)
Uled = DoubleVar()
AuswahlMenue.add_radiobutton(label="rot", \
                       variable=Uled,value=1.6, \
                       background="red")
AuswahlMenue.add_radiobutton(label="grün", \
                       variable=Uled,value=2.1, \
                       background="green")
AuswahlMenue.add_radiobutton(label="gelb", \
                       variable=Uled,value=2.2,\
                       background="yellow")
AuswahlMenue.add_radiobutton(label="blau", \
                       variable=Uled,value=2.9,\
                       background="blue")
AuswahlMenue.add_radiobutton(label="wei"s", \
                       variable=Uled,value=4.0,\
                       background="white")
MenueLeiste.add_cascade(label="Farbe", menu=AuswahlMenue)
Vielleicht ist Ihnen die Ressouce tearoff bei der Erstellung des Datei-Menüs aufgefallen. Mit tearoff=0 wurde die Möglichkeit abgeschaltet, Menüs einfach von der Menüleiste abreißen zu können. Tk sieht dies standardmäßig vor. Probieren Sie es aus, indem Sie tearoff=0 einfach entfernen.

Zugriffe auf Ressourcen

Über die benamten Parameter können Sie Ressourcen eines Kontrollelements setzen, wie beispielsweise:
Knopf = Button(Fenster, text = "Ende", command = ende)
Die Beschriftung (text) wurde auf "Ende" gesetzt und der Callback (command) auf die Funktion ende gelenkt.

Wollen Sie solche Ressourcen nachträglich verändern, können Sie die Methode configure() aufrufen.

knopf.configure(text = "Ende")

Wenn Sie übrigens die Methode configure() ohne Parameter aufrufen, erhalten Sie für die Abkürzungen wie bd ein Zwei-Tupel, dessen zweiter Wert den langen Namen enthält, im Falle von bd ist dies borderwidth. Für alle anderen Optionen erhalten Sie ein Fünf-Tupel. Es enthält den Namen der Option, den Verweisnamen, den Namen der Klasse, der Vorgabewert und schließlich der aktuelle Wert.

Die Ressourcen können Si auch über den Interpreter erfragen, indem Sie für die Klasse configure ohne Parameter aufrufen.

$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
>>> tkinter.Button().configure()
{'activebackground': ('activebackground', 'activeBackground', 'Foreground', '#ececec', '#ffffff'),
'activeforeground': ('activeforeground', 'activeForeground', 'Background', '#000000', '#000000'),
'anchor': ('anchor', 'anchor', 'Anchor', <index object: 'center'>, 'center'),
'background': ('background', 'background', 'Background', '#d9d9d9', '#edeceb'),
'bd': ('bd', '-borderwidth'),
'bg': ('bg', '-background'),
'bitmap': ('bitmap', 'bitmap', 'Bitmap', '', ''),
'borderwidth': ('borderwidth', 'borderWidth', 'BorderWidth', <pixel object: '1'>, <pixel object: '1'>),
'command': ('command', 'command', 'Command', '', ''),
'compound': ('compound', 'compound', 'Compound', <index object: 'none'>, 'none'),
'cursor': ('cursor', 'cursor', 'Cursor', '', ''),
'default': ('default', 'default', 'Default', <index object: 'disabled'>, 'disabled'),
'disabledforeground': ('disabledforeground', 'disabledForeground', 'DisabledForeground', <color object: '#a3a3a3'>, '#a3a3a3'),
'fg': ('fg', '-foreground'),
'font': ('font', 'font', 'Font', <font object: 'TkDefaultFont'>, 'TkDefaultFont'),
'foreground': ('foreground', 'foreground', 'Foreground', '#000000', '#000000'),
'height': ('height', 'height', 'Height', 0, 0),
'highlightbackground': ('highlightbackground', 'highlightBackground', 'HighlightBackground', '#d9d9d9', '#edeceb'),
'highlightcolor': ('highlightcolor', 'highlightColor', 'HighlightColor', '#000000', '#000000'),
'highlightthickness': ('highlightthickness', 'highlightThickness', 'HighlightThickness', <pixel object: '1'>, <pixel object: '1'>),
'image': ('image', 'image', 'Image', '', ''),
'justify': ('justify', 'justify', 'Justify', <index object: 'center'>, 'center'),
'overrelief': ('overrelief', 'overRelief', 'OverRelief', '', ''),
'padx': ('padx', 'padX', 'Pad', <pixel object: '3m'>, <pixel object: '3m'>),
'pady': ('pady', 'padY', 'Pad', <pixel object: '1m'>, <pixel object: '1m'>),
'relief': ('relief', 'relief', 'Relief', <index object: 'raised'>, 'raised'),
'repeatdelay': ('repeatdelay', 'repeatDelay', 'RepeatDelay', 0, 0),
'repeatinterval': ('repeatinterval', 'repeatInterval', 'RepeatInterval', 0, 0),
'state': ('state', 'state', 'State', <index object: 'normal'>, 'normal'),
'takefocus': ('takefocus', 'takeFocus', 'TakeFocus', '', ''),
'text': ('text', 'text', 'Text', '', ''),
'textvariable': ('textvariable', 'textVariable', 'Variable', '', ''),
'underline': ('underline', 'underline', 'Underline', -1, -1),
'width': ('width', 'width', 'Width', 0, 0),
'wraplength': ('wraplength', 'wrapLength', 'WrapLength', <pixel object: '0'>, <pixel object: '0'>)}
>>>

Sie können Ressourcen über eine Dictionary-Funktionalität des Buttons verändern. Dazu setzen Sie die Ressource als Schlüsselwert in rechteckigen Klammern ein.

Knopf["text"] = "Ende"

Links