navigation Navigation


Inhaltsverzeichnis

1 - Grundlagen


Tkinter ist die Standard-Bibliothek für die Erstellung von grafischen Benutzeroberflächen (GUIs) in Python. Sie ermöglicht es dir, professionelle Desktop-Anwendungen mit Fenstern, Buttons, Eingabefeldern und vielen anderen Elementen zu erstellen – ohne externe Abhängigkeiten.

Inhaltsverzeichnis

    Einführung

    Tkinter (Tk Interface) ist Pythons Standard GUI-Bibliothek und eine Python-Schnittstelle für Tk GUI Toolkit. Tk wurde ursprünglich für die Programmiersprache Tcl entwickelt, wurde aber für viele Sprachen portiert, darunter Python.

    Kernmerkmale

    • Plattformübergreifend: Läuft auf Window, macOS und Linux
    • Standardbibliothek: In Python bereits integriert
    • Ausgereift und stabil: Seit 1991 in Entwicklung
    • Event-basiert: Reagiert auf Benutzerinteraktionen
    • Widget-basiert: Modularer Aufbau aus UI-Komponenten

    Installation & Setup

    Verfügbarkeit prüfen

    Tkinter ist normalerweise bereits mit Python installiert. Um dies zu prüfen, kann man folgendes kleines Python-Programm (Script) verwenden.

    Dafür können wir beispielsweise eine Datei namens test_tkinter.py mit nachfolgendem Inhalt erstellen. Danach kann man dieses Script einfach mit python3 test_tkinter.py ausführen.

    Tkinter prüfen
    import tkinter as tk
    
    print(f"Tkinter Version: {tk.TkVersion}")
    print(f"Tcl Version: {tk.TclVersion}")
    print(f"Tkinter ist verfügbar")
    Tkinter Version: 9.0
    Tcl Version: 9.0
    Tkinter ist verfügbar

    Installation (falls nicht vorhanden)

    macOS

    brew install python-tk@3.14

    Linux (Ubuntu/Debian)

    sudo apt update
    sudo apt install python3-tk

    Linux (Fedora)

    sudo dnf install python3-tkinter

    Windows

    Tkinter wird automatisch mit Python installiert. Hier ist wichtig sicherzustellen, dass “tcl/tk and IDLE” während der Installation aktiviert ist.

    Erstes Tkinter Programm

    In diesem Beispiel schreiben wir das minimalste und erste Tkinter Programm.

    Erstes Programm
    import tkinter as tk
    
    # Hauptfenster erstellen
    root = tk.Tk()
    
    # Event-Loop starten
    root.mainloop()

    Wenn wir das Programm ausführen, erhalten wir unser App-Fenster.

    Tkinter - Erstes Programm

    Was passiert hier genau?

    1. import tkinter as tk - Importiert Tkinter (mit tk Alias)
    2. root = tk.Tk() - Erstellt das Hauptfenster (Root-Window)
    3. root.mainloop() - Startet die Event-Loop (Programm wartet auf Events)

    Programm mit Label

    Im nächsten Schritt platzieren wir zur Veranschaulichung ein Label-Widget. Diese werden später genauer erläutert.

    Dazu erstellen wir die Datei basic_label_widget.py mit folgendem Inhalt.

    Basic Widgets
    import tkinter as tk
    
    # Hauptfenster erstellen
    root = tk.Tk()
    
    # Titel des Fensters setzen
    root.title("Basic Widgets")
    
    # Größe des Fensters festlegen
    root.geometry("500x300") # Breite x Höhe
    
    # Label-Widget erstellen
    label_one = tk.Label(
        master=root,
        text="Hallo Tkinter",
        font=("Arial", 24),
        fg="#246990"
    )
    
    # Label im Fenster platzieren
    label_one.pack(pady=50)
    
    # Event-Loop starten
    root.mainloop()

    Nach der Ausführung mit python3 basic_label_widget.py erhalten wir folgendes Programm.

    Tkinter - Basis Label Widget

    Was ist hier neu?

    • root.title() - Setzt den Fenster-Titel
    • root.geometry() - Setzt die Fenstergröße (Format: “BreitexHöhe”)
    • tk.Label() - Erstellt ein Text-Widget
    • label_one.pack() - Platziert das Widget im Fenster
    • pady=50 - Fügt vertikalen Abstand hinzu

    Programm mit Label und Button

    Nun bauen wir unser Beispiel ein wenig aus und fügen einen Button hinzu, auf den wir klicken und eine Aktion ausführen können.

    Label und Button
    import tkinter as tk
    
    # Funktion für Button
    # Wird aufgerufen, wenn der Button geklickt wird
    def button_action():
        label_one.configure(text="Button geklickt!")
        button_one.configure(state="disabled")
    
    # Hauptfenster
    root = tk.Tk()
    root.title("Label und Button")
    root.geometry("500x300")
    
    # Label
    label_one = tk.Label(
        master=root,
        text="Klicke den Button!"
        font=("Arial", 18)
    )
    label_one.pack(pady=30)
    
    # Button
    button_one = tk.Button(
        master=root,
        text="Klick mich",
        font=("Arial", 14),
        bg="#246990",
        fg="white",
        padx=20,
        pady=10,
        command=button_action
    )
    button_one.pack()
    
    # Event-Loop
    root.mainloop()

    Mit diesem Code erhalten wir eine Applikation, welche uns einen Label und einen Button bereitstellt. Mit dem Klick auf den Button können wir sowohl den Label als auch den Button aktualisieren.

    Tkinter - App mit Label und Button (1)

    Initialer Zustand

    Tkinter - App mit Label und Button (2)

    Button geklickt

    Event-Loop

    Was ist die Event-Loop

    Die Event-Loop ist das Herzstück vieler GUI-Anwendungen.

    +-------------------------------------------+
    |  Start: root.mainloop()                   |
    +----------------------+--------------------+
                        |
                        v
                +----------------------+
                |  Warte auf Event    |<-----------+
                +----------+-----------+           |
                            |                      |
                            v                      |
                +----------------------+           |
                |  Event aufgetreten? |            |
                +----------+-----------+           |
                            |                      |
                    +--------+--------+            |
                    |                 |            |
                    Ja              Nein           |
                    |                 |            |
                    v                 +------------+
        +-------------------+
        | Event             |
        | verarbeiten       |
        +---------+---------+
                    |
                    v
        +-------------------+
        | Callbacks         |
        | ausführen         |
        +---------+---------+
                    |
                    v
        +-------------------+
        | GUI               |
        | aktualisieren     |
        +---------+---------+
                    |
                    +------------------------------>

    Tkinter ist kein reines Python-GUI-Toolkit. Es ist ein Python-Binding zu Tcl/Tk. Das bedeutet:

    • Die Python-Methoden (z.B. button = tk.Button(...)) erzeugen Tcl/Tk-Objekte
    • Tkinter kommuniziert per eingebettetem Tcl-Interpreter
    • Die Event-Loop gehört dem Tcl/Tk-Interpreter, nicht Python

    Die zentrale Schleife (Loop) ist Tk.mainloop(), aber intern ist es Tcl/Tk, nicht Python.

    Ablauf

    Wir haben folgenden Code.

    root = tk.Tk()
    root.mainloop()

    Wenn wir diesen Code ausführen, passiert Folgendes:

    1. Tkinter übergibt die Kontrolle an Tcl/Tk
    2. Tcl/Tk startet seine Hauptschleife:
      • Überprüft Input-Events (X11 / WinAPI / macOS EventQueue)
      • Führt Callbacks aus (command=..., bind=..., Timer-Events)
      • Zeichent die Widgets neu
      • Plant das Neu-Zeichnen, Idle-Tasks, interne Updates
    3. Python blockiert, bis die Schleife beendet wird

    Während mainloop() läuft, ruft NICHT Python Tkinter auf - Tcl/Tk ruft die definierten Python-Callbacks auf.

    Beispiel - Event-Loop

    Schauen wir uns ein Basis-Beispiel für eine Event-Loop an.

    Beispiel - Event-Loop
    import tkinter as tk
    from datetime import datetime
    
    
    def update_time():
        current_time = datetime.now().strftime("%H:%M:%S")
        time_label.configure(text=f"Aktuelle Zeit: {current_time}")
        root.after(1000, update_time)
    
    
    def on_mouse_enter(event):
        hover_label.configure(
            text="Maus über dem Label",
            bg="lightblue"
        )
    
    
    def on_mouse_leave(event):
        hover_label.configure(
            text="Bewege die Maus hierher",
            bg="lightgrey"
        )
    
    
    root = tk.Tk()
    root.title("Event-Loop Demo")
    root.geometry("500x300")
    
    time_label = tk.Label(
        master=root,
        font=("Arial", 16)
    )
    time_label.pack(pady=20)
    
    # Starte die Zeit-Aktualisierung
    update_time()
    
    hover_label = tk.Label(
        master=root,
        text="Bewege die Maus hierher",
        font=("Arial", 16),
        bg="lightgrey",
        padx=20,
        pady=20
    )
    hover_label.pack(pady=20)
    
    hover_label.bind("<Enter>", on_mouse_enter)
    hover_label.bind("<Leave>", on_mouse_leave)
    
    click_count = 0
    counter_label = tk.Label(
        master=root,
        text=f"Klicks: {click_count}",
        font=("Arial", 16)
    )
    counter_label.pack(pady=20)
    
    
    def increment_counter():
        global click_count
        click_count += 1
        counter_label.configure(text=f"Klicks: {click_count}")
    
    
    counter_button = tk.Button(
        master=root,
        text="Klick mich",
        command=increment_counter
    )
    counter_button.pack()
    
    root.mainloop()

    Wenn wir diesen Code ausführen, erhalten wir eine Anwendung mit ein paar Widgets, mit welchen wir interagieren können. Dabei aktualisiert sich die jeweiligen Zustände jeweils.

    Tkinter - Demo der Event Loop (1)

    Tkinter - Demo der Event Loop (2)

    Was in diesem Beispiel neu war, sind folgende Konzepte.

    • after(ms, callback) - Ruft eine Funktion nach einer Verzögerung auf
    • bind(event, handler) - Verbindet Events mit Handler-Funktionen
    • Event-Handler erhalten ein event Objekt mit Details

    Grundstruktur einer Tkinter-Anwendung

    Objektorientierter Ansatz

    Für größere Anwendungen ist eine klare Struktur wichtig. Schauen wir uns ein Beispiel an.

    Beispiel
    import tkinter as tk
    
    class Application(tk.Tk):
        """Haupt-Anwendungsklasse"""
    
        def __init__(self):
            # Initialisierung
            super().__init__()
    
            # Fenster-Konfiguration
            self.title("Tkinter-App")
            self.geometry("500x300")
    
            # UI erstellen
            self.create_widgets()
    
        def create_widgets(self):
            # Erstellt UI-Komponenten
    
            # Header
            header = tk.Label(
                master=self,
                text="Willkommen",
                font=("Arial", 20, bold),
                bg="lightblue",
                pady=10
            )
            header.pack(fill="x")
    
            # Haupt-Bereich
            main_frame = tk.Frame(
                master=self,
                bg="white"
            )
            main_frame.pack(
                fill="both",
                expand=True,
                padx=20,
                pady=20
            )
    
            # Inhalt
            tk.Label(
                master=main_frame,
                text="Das ist eine strukturierte Anwendung",
                font=("Arial", 12),
                bg="white"
            ).pack(pady=10)
    
            # Button
            tk.Button(
                master=main_frame,
                text="Aktion ausführen",
                command=self.handle_button_click
            ).pack(pady=10)
    
            # Status-Label
            self.status_label = tk.Label(
                master=main_frame,
                text="Bereit",
                font=("Arial", 10),
                fg="green",
                bg="white"
            )
            self.status_label.pack(pady=10)
    
        def handle_button_click(self):
            # Führt eine Aktion aus
            self.status_label.configure(
                text="Aktion wurde ausgeführt",
                fg="#246990"
            )
    
    
    if __name__ == "__main__":
        app = Application()
        app.mainloop()

    Mit diesem Ansatz ist es für uns möglich, Anwendungen mit mehr Objekt-orientiertem Ansatz zu schreiben. Das gibt dem Code mehr Struktur und bessere Aufteilung.

    Tkinter - OOP Struktur Beispiel (1)

    Tkinter - OOP Struktur Beispiel (2)

    Tkinter vs Ttk

    Tkinter bietet zwei Sets von Widgets.

    1. tkinter - Klassische Widgets (tk.Button, tk.Label, etc.)
    2. ttk - Themed Widgets (ttk.Button, ttk.Label, etc.)
    Aspekttkinterttk
    AussehenPlatform-basicPlatform-native / Themed
    StylingÜber Widget-OptionenÜber ttk.Style
    PerformanceGutBesser
    ModernitätAltmodischModern
    OptionenMehr direkte OptionenWeniger direkte Optionen

    Verfügbare ttk-Widgets

    • Button, Checkbutton, Radiobutton
    • Label, Entry
    • Frame, LabelFrame
    • Combobox (Dropdown)
    • Progressbar
    • Scrollbar
    • Notebook (Tabs)
    • Treeview
    • Separator
    • Sizegrip
    • Scale

    Nur in tkinter verfügbar

    • Canvas
    • Text
    • Listbox
    • Menu
    • Spinbox (auch in ttk, aber anders)
    • OptionMenu
    • Toplevel

    Nun schauen wir uns den Vergleich direkt an einem Beispiel an, damit wir auch visuell sehen, wie sich die Widgets unterscheiden.

    Vergleich tk vs. ttk
    import tkinter as tk
    from tkinter import ttk
    
    root = tk.Tk()
    root.title("Vergleich tk vs. ttk")
    root.geometry("600x400")
    
    # Überschrift
    tk.Label(
        master=root,
        text="Widget-Vergleich: tk vs. ttk",
        font=("Arial", 16, "bold")
    ).pack(pady=10)
    
    # Container
    container = tk.Frame(master=root)
    container.pack(
        fill="both",
        expand=True,
        padx=20,
        pady=10
    )
    
    # Linke Spalte: tkinter
    tk_frame = tk.LabelFrame(
        master=container,
        text="tkinter Widgets",
        font=("Arial", 12, "bold"),
        padx=10,
        pady=10
    )
    tk_frame.pack(
        side="left",
        fill="both",
        expand=True,
        padx=(0, 5)
    )
    
    tk.Label(
        master=tk_frame,
        text="Label (tkinter)"
    ).pack(pady=5)
    
    tk.Button(
        master=tk_frame,
        text="Button (tkinter)"
    ).pack(pady=5)
    
    tk.Checkbutton(
        master=tk_frame,
        text="Checkbutton (tkinter)"
    ).pack(pady=5)
    
    tk.Radiobutton(
        master=tk_frame,
        text="Radiobutton (tkinter)"
    ).pack(pady=5)
    
    tk.Entry(master=tk_frame).pack(pady=5)
    
    tk.Scale(
        master=tk_frame, 
        from_=0, 
        to=100,
        orient="horizontal"
    ).pack(pady=5)
    
    
    # Rechte Spalte: ttk
    ttk_frame = ttk.LabelFrame(
        master=container,
        text="ttk Widgets (Themed)",
        padding=10
    )
    ttk_frame.pack(
        side="right",
        fill="both",
        expand=True,
        padx=(5, 0)
    )
    
    ttk.Label(
        master=ttk_frame,
        text="Label (ttk)"
    ).pack(pady=5)
    
    ttk.Button(
        master=ttk_frame,
        text="Button (ttk)"
    ).pack(pady=5)
    
    ttk.Checkbutton(
        master=ttk_frame,
        text="Checkbutton (ttk)"
    ).pack(pady=5)
    
    ttk.Radiobutton(
        master=ttk_frame,
        text="Radiobutton (ttk)"
    ).pack(pady=5)
    
    ttk.Entry(master=ttk_frame).pack(pady=5)
    
    ttk.Scale(
        master=ttk_frame,
        from_=0,
        to=100,
        orient="horizontal"
    ).pack(pady=5)
    
    # Zusätzlich ttk-spezifische Widgets
    ttk.Separator(
        master=ttk_frame,
        orient="horizontal"
    ).pack(fill="x", pady=10)
    
    ttk.Progressbar(
        master=ttk_frame,
        mode="determinate",
        value=50
    ).pack(pady=5)
    
    ttk.Combobox(
        master=ttk_frame,
        values=[
            "Option 1",
            "Option 2",
            "Option 3"
        ]
    ).pack(pady=5)
    
    root.mainloop()

    Mit dieser Applikation haben wir Sektionen, in welchen wir die Widgets nebeneinander sehen. Bei ttk sehen wir, dass auch das dunkle Design des Betriebssystems automatisch unterstützt wird.

    Tkinter - tk und ttk Vergleich (1)

    Tkinter - tk und ttk Vergleich (2)

    Praktisches Beispiel

    Zum Abschluß der Einführung und Übersicht über Tkinter, bauen wir ein Beispiel mit verschiedenen Widgets auf. Man muss nicht alle Widgets an dieser Stelle verstehen, da diese im späteren Verlauf im Detail erklärt werden.

    Beispiel
    import tkinter as tk
    from tkinter import ttk, messagebox
    from datetime import datetime
    
    
    class PersonalInfoApp(tk.Tk):
    
        def __init__(self):
            super().__init__()
    
            # Daten-Storage
            self.persons = []
    
            # Fenster-Setup
            self.setup_window()
    
            # UI erstellen
            self.create_widgets()
    
            # Willkommensnachricht
            self.update_status("Bereit - Geben Sie Ihre Daten ein")
    
    
        def setup_window(self):
            """
            Konfiguriert das Hauptfenster
            """
    
            self.title("Personal Info Manager")
            self.geometry("700x500")
    
            # Minimum-Größe festlegen
            self.minsize(600, 400)
    
            # Beim Schließen nachfragen
            self.protocol("WM_DELETE_WINDOW", self.on_closing)
    
    
        def create_widgets(self):
            """
            Erstellt alle UI-Komponenten
            """
    
            # Haupt-Container mit Padding
            main_container = ttk.Frame(
                master=self,
                padding=10
            )
            main_container.pack(fill="both", expand=True)
    
            # Titel
            title_label = tk.Label(
                master=main_container,
                text="📋 Personal Info Manager",
                font=("Arial", 18, "bold"),
                bg="#4CAF50",
                fg="white",
                pady=10
            )
            title_label.pack(fill="x")
    
            # Eingabebereich
            self.create_input_section(main_container)
    
            # Listen-Bereich
            self.create_list_section(main_container)
    
            # Statusbar
            self.status_bar = ttk.Label(
                master=self,
                text="Bereit",
                relief="sunken",
                anchor="w"
            )
            self.status_bar.pack(side="bottom", fill="x")
    
        def create_input_section(self, parent):
            """
            Erstellt den Eingabebereich
            """
    
            input_frame = ttk.LabelFrame(
                master=parent,
                text="Neue Person hinzufügen",
                padding=10
            )
            input_frame.pack(fill="x", pady=(10, 5))
    
            # Grid-Layout für Formular
    
            # - Name
            ttk.Label(
                master=input_frame,
                text="Name:"
            ).grid(
                row=0,
                column=0,
                sticky="w",
                pady=5
            )
            self.name_var = tk.StringVar()
            self.name_entry = ttk.Entry(
                master=input_frame,
                textvariable=self.name_var,
                width=30
            )
            self.name_entry.grid(
                row=0,
                column=1,
                sticky="ew",
                pady=5,
                padx=5
            )
    
            # - Alter
            ttk.Label(
                master=input_frame,
                text="Alter:"
            ).grid(
                row=1,
                column=0,
                sticky="w",
                pady=5
            )
    
            self.age_var = tk.StringVar()
            self.age_spinbox = ttk.Spinbox(
                master=input_frame,
                from_=0,
                to=120,
                textvariable=self.age_var,
                width=10
            )
            self.age_spinbox.grid(
                row=1,
                column=1,
                sticky="w",
                pady=5,
                padx=5
            )
    
            # - Stadt
            ttk.Label(
                master=input_frame,
                text="Stadt:"
            ).grid(
                row=2,
                column=0,
                sticky="w",
                pady=5
            )
    
            self.city_var = tk.StringVar()
            self.city_combo = ttk.Combobox(
                master=input_frame,
                textvariable=self.city_var,
                values=[
                    "Berlin",
                    "München",
                    "Hamburg",
                    "Köln",
                    "Frankfurt"
                ],
                width=28
            )
            self.city_combo.grid(
                row=2,
                column=1,
                sticky="ew",
                pady=5,
                padx=5
            )
    
    
            # Button-Frame
            button_frame = ttk.Frame(master=input_frame)
            button_frame.grid(
                row=3,
                column=0,
                columnspan=2,
                pady=10
            )
    
            ttk.Button(
                master=button_frame,
                text="Hinzufügen",
                command=self.add_person
            ).pack(side="left", padx=5)
    
            ttk.Button(
                master=button_frame,
                text="Felder leeren",
                command=self.clear_fields
            ).pack(side="left", padx=5)
    
            # Grid-Gewichtung für Responsive-Verhalten
            input_frame.columnconfigure(1, weight=1)
    
            # Enter-Taste zum Hinzufügen
            self.name_entry.bind("<Return>", lambda e: self.add_person())
            self.age_spinbox.bind("<Return>", lambda e: self.add_person())
            self.city_combo.bind("<Return>", lambda e: self.add_person())
    
        def create_list_section(self, parent):
            """
            Erstellt den Listen-Bereich
            """
    
            list_frame = ttk.LabelFrame(
                master=parent,
                text="Gespeicherte Personen",
                padding=10
            )
            list_frame.pack(
                fill="both",
                expand=True,
                pady=(5, 10)
            )
    
            # Treeview mit Scrollbar
            tree_container = ttk.Frame(master=list_frame)
            tree_container.pack(fill="both", expand=True)
    
            # Scrollbars
            vsb = ttk.Scrollbar(
                master=tree_container,
                orient="vertical"
            )
            vsb.pack(side="right", fill="y")
    
            hsb = ttk.Scrollbar(
                master=tree_container,
                orient="horizontal"
            )
            hsb.pack(side="bottom", fill="x")
    
            # Treeview
            self.tree = ttk.Treeview(
                master=tree_container,
                columns=(
                    "Name",
                    "Alter",
                    "Stadt",
                    "Hinzugefügt"
                ),
                show="headings",
                yscrollcommand=vsb.set,
                xscrollcommand=hsb.set
            )
    
            # Scrollbars konfigurieren
            vsb.configure(command=self.tree.yview)
            hsb.configure(command=self.tree.xview)
    
            # Spalten-Header
            self.tree.heading("Name", text="Name")
            self.tree.heading("Alter", text="Alter")
            self.tree.heading("Stadt", text="Stadt")
            self.tree.heading("Hinzugefügt", text="Hinzugefügt am")
    
            # Spaltenbreiten
            self.tree.column("Name", width=150)
            self.tree.column("Alter", width=80)
            self.tree.column("Stadt", width=120)
            self.tree.column("Hinzugefügt", width=150)
    
            self.tree.pack(fill="both", expand=True)
    
            # Button-Frame unter der Liste
            button_frame = ttk.Frame(master=list_frame)
            button_frame.pack(fill="x", pady=(10, 0))
    
            ttk.Button(
                master=button_frame,
                text="Ausgewählte löschen",
                command=self.delete_selected
            ).pack(side="left", padx=5)
    
            ttk.Button(
                master=button_frame,
                text="Alle löschen",
                command=self.delete_all
            ).pack(side="left", padx=5)
    
            self.count_label = ttk.Label(
                master=button_frame,
                text="Gesamt: 0"
            )
    
            self.count_label.pack(side="right", padx=5)
    
        def add_person(self):
            """
            Fügt eine Person zur Liste hinzu
            """
    
            name = self.name_var.get().strip()
            age = self.age_var.get().strip()
            city = self.city_var.get().strip()
    
            # Validierung
            if not name:
                messagebox.showwarning("Warnung", "Bitte geben Sie einen Namen ein.")
                self.name_entry.focus()
                return
    
            if not age or not age.isdigit():
                messagebox.showwarning("Warnung", "Bitte geben Sie ein gültiges Alter ein.")
                self.age_spinbox.focus()
                return
    
            if not city:
                messagebox.showwarning("Warnung", "Bitte wählen Sie eine Stadt.")
                self.city_combo.focus()
                return
    
            # Zeitstempel
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    
            # Zur Liste hinzufügen
            person = {
                "name": name,
                "age": age,
                "city": city,
                "timestamp": timestamp
            }
            self.persons.append(person)
    
            # In Treeview einfügen
            
            self.tree.insert(
                "",
                "end",
                values=(name, age, city, timestamp)
            )
    
            # Felder leeren
            self.clear_fields()
    
            # Status aktualisieren
            self.update_count()
            self.update_status(f"'{name}' wurde hinzugefügt")
    
            # Focus zurück zum Namen-Feld
            self.name_entry.focus()
    
        def clear_fields(self):
            """
            Leert alle Eingabefelder
            """
    
            self.name_var.set("")
            self.age_var.set("")
            self.city_var.set("")
            self.name_entry.focus()
    
        def delete_selected(self):
            """
            Löscht die ausgewählten Einträge
            """
    
            selected_items = self.tree.selection()
    
            if not selected_items:
                messagebox.showinfo("Info", "Bitte wählen Sie einen Eintrag aus.")
                return
    
            # Bestätigung
            if messagebox.askyesno(
                "Bestätigung",
                f"Möchten Sie {len(selected_items)} Eintrag/Einträge löschen?"
            ):
                for item in selected_items:
                    self.tree.delete(item)
    
                self.update_count()
                self.update_status(f"{len(selected_items)} Eintrag/Einträge gelöscht")
    
        def delete_all(self):
            """
            Löscht alle Einträge
            """
    
            if not self.tree.get_children():
                messagebox.showinfo("Info", "Liste ist bereits leer.")
                return
    
            if messagebox.askyesno(
                "Bestätigung",
                "Möchten Sie wirklich alle Einträge löschen?"
            ):
                self.tree.delete(*self.tree.get_children())
                self.persons.clear()
                self.update_count()
                self.update_status("Alle Einträge gelöscht")
    
        def update_count(self):
            """
            Aktualisiert die Anzahl-Anzeige
            """
    
            count = len(self.tree.get_children())
            self.count_label.configure(text=f"Gesamt: {count}")
    
        def update_status(self, message):
            """
            Aktualisiert die Statusbar
            """
    
            self.status_bar.configure(
                text=f"{message} | {datetime.now().strftime('%H:%M:%S')}"
            )
    
        def on_closing(self):
            """
            Wird beim Schließen des Fensters aufgerufen
            """
    
            if self.persons:
                if messagebox.askyesno(
                    "Beenden",
                    "Es gibt ungespeicherte Daten. Wirklich beenden?"
                ):
                    self.destroy()
            else:
                self.destroy()
    
    
    
    if __name__ == "__main__":
        app = PersonalInfoApp()
        app.mainloop()

    Wenn wir dieses Programm ausführen, erhalten wir folgende schöne Applikation, welche bereits einiges an Layouting und Funktionalität demonstriert.

    Tkinter - Widgets-Sammlung als Beispiel (Einführung)