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.
Noch keine Stimmen abgegeben
1 Kommentare
  • Kleine Anmerkung: Mit style_tab.layout('TNotebook.Tab', []) wird das Styling global f├╝r alle Notebook Tab-s gesetzt. Besser w├Ąre es mit style.configure('Custom', ...) und notebook.tab(tab, style='Custom') gezielt nur gew├Ąhlte Tabs stylen. von BeautifulCode am 19 Mai 2023

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.