Master-Detailansicht mit Python und Tkinter
Master-Detail-Ansichten werden häufig in GUI-Anwendungen verwendet, um zusammengehörige Daten hierarchisch anzuzeigen. Wir zeigen dazu zwei Implementierungen in Tkinter mit Python.
In unserem ersten Ansatz verwenden wir tk.Listbox
zur Darstellung einer Liste von Items
und ein tk.Label
Element für die Detailansicht eines gewählten Items.
Natürlich kann statt des Label-Elements auch eine komplexe UI verwendet werden.
In dem Beispiel geht es nur um die Grundlegende Funktionsweise zwischen der Listen- und Detaildarstellung:
import tkinter as tk
# Array mit Beispieldaten
items = [
{'name': 'JBerries 1', 'beschreibung': 'Das sind Details zu JBerries 1'},
{'name': 'JBerries 2', 'beschreibung': 'Das sind Details zu JBerries 1'},
{'name': 'JBerries 3', 'beschreibung': 'Das sind Details zu JBerries 1'},
]
root = tk.Tk()
# Listbox Element
listbox = tk.Listbox(root)
listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Beispieldaten in die UI einfügen
for item in items:
listbox.insert(tk.END, item['name'])
# Details Label
detail_frame = tk.Frame(root)
detail_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
# Callback um die Detailansicht aufzurufen
def on_select(event):
# Index des selektierten Items
index = event.widget.curselection()[0]
# Zu dem Idex das Element aus der Liste auswählen
item = items[index]
# Detailansicht aktualisieren
name_label.configure(text=item['name'])
details_label.configure(text=item['beschreibung'])
# Binden des Callbacks an das ListboxSelect-Event
listbox.bind('<<ListboxSelect>>', on_select)
# Detailansicht
name_label = tk.Label(detail_frame, font=('Arial', 20))
name_label.pack(side=tk.TOP, pady=10)
details_label = tk.Label(detail_frame, font=('Arial', 12))
details_label.pack(side=tk.TOP, padx=10)
root.mainloop()
Im ersten Schritt wird die Listenansicht mit den Beispieldaten aufgebaut.
Um die Detaildarstellung anzuzeigen, benutzen wir einen on_select
Listner:
Aus dem event.widget.curselection
Event bekommen wir den Index des selektierten Items und
können damit das zugehörige Objekt aus dem Array holen.
Anschliessend müssen wir nur noch das Label über details_label.configure(text=item['beschreibung'])
aktualisieren.
In zweiten Ansatz verwenden wir ttk.Notebook
:
root = tk.Tk()
root.title("Master/Details mit ttk.Notebook")
# Notebook (tabs container)
notebook = ttk.Notebook(root)
style_tab = ttk.Style()
style_tab.layout('TNotebook.Tab', [])
# Tabs für Übersicht bzw. Detailansicht
tab_overview = ttk.Frame(notebook)
tab_details = ttk.Frame(notebook)
command_details = lambda: notebook.select(tab_details)
tk.Label(tab_overview, text="Übersicht").pack()
tk.Button(tab_overview, text="Zur Detailansicht", command=command_details).pack()
command_overview = lambda: notebook.select(tab_overview)
tk.Label(tab_details, text="Details").pack()
tk.Button(tab_details, text="Zurück zur Übersicht", command=command_overview).pack()
notebook.add(tab_overview, text="")
notebook.add(tab_details, text="")
notebook.pack()
root.mainloop()
Eigentlich verwendet man ttk.Notebook
um Tabs anzuzeigen.
Der Trick hier ist, dass wir nur zwei Tabs benutzen und zwischen diesen für die Übersicht bzw. Detailsdarstellung umschalten.
Dabei ändern wir mit style_tab.layout('TNotebook.Tab', [])
das Styling der Tabs des ttk.Notebook
so, dass die eigentlichen Tabs gar nicht sichtbar sind.