Zum Inhalt springen

Aufgabe 22 - To-do-Liste als Desktop-App

Zu Zen-Modus wechseln

Ihre erste vollständige Desktop-Anwendung: eine To-do-Liste mit Tkinter. Im Zentrum steht nicht die Oberfläche selbst, sondern die Architekturregel des Kapitels: Die Fachlogik weiß nichts von der GUI und bleibt dadurch testbar (siehe Kapitel GUI mit Python). Die Reihenfolge der Teile ist deshalb verbindlich: erst die Logik samt Tests, dann die Oberfläche.

  • Kapitel GUI mit Python vollständig; Kapitel Exceptions, Testen mit pytest und Dateien und Datenformate.
  • Python mit Tkinter (Standardbibliothek), pytest, VS Code, ein Git-Repository.
  • Sie bauen eine GUI mit Widgets, grid-Layout und Ereignisbehandlung als Klasse auf.
  • Sie trennen Fachlogik und Oberfläche in eigene Module und testen die Logik automatisiert.
  • Sie fangen Fehlbedienung ab und melden sie benutzergerecht über Dialoge.
  • Reproduktion: die GUI-Grundbausteine (Fenster, Widgets, Handler) anwenden (Teile A und B).
  • Reorganisation und Transfer: die Schichtentrennung auf ein eigenes Programm übertragen und Persistenz integrieren (Teile B und C).
  • Reflexion, Problemlösung und Urteilsbildung: die Oberfläche gegen Fehlbedienung absichern, den Entwurf strukturieren und Architekturentscheidungen begründen (Teile C und D).

Die Übung ist auf etwa zwei Stunden ausgelegt. Teil D ist der Expertenteil.

Teil A - Fachlogik zuerst, ohne ein einziges Fenster

Abschnitt betitelt „Teil A - Fachlogik zuerst, ohne ein einziges Fenster“
  1. Implementieren Sie in todo_logic.py die Klasse TodoList mit add(text, priority) (Priorität 1 bis 3; leerer Text oder ungültige Priorität führen zu ValueError), complete(index), remove(index), open_tasks() und completed_tasks().
  2. Schreiben Sie in test_todo.py fünf pytest-Tests: hinzufügen, erledigen, ungültige Priorität (pytest.raises), leerer Text, ungültiger Index.
  3. Alle Tests grün, bevor irgendetwas mit Tkinter passiert. Halten Sie in einem Kommentar fest, warum diese Reihenfolge nur funktioniert, weil die Klasse kein Tkinter importiert.
  1. Bauen Sie in todo_gui.py eine Klasse TodoApp (nach dem Muster des Kapitels): Eingabefeld, Prioritätsauswahl (1 bis 3), Button “Add”, eine Listbox mit den offenen Aufgaben, Buttons “Done” und “Delete” für den ausgewählten Eintrag, ein Label 3 open / 5 done.
  2. Layout mit grid: Beschriftungen rechtsbündig, Eingabespalte wächst mit dem Fenster (columnconfigure mit weight), einheitliche Abstände mit padx/pady.
  3. Anzeigeformat der Listbox: [!!!] SEW homework, Rufzeichen entsprechend der Priorität, sortiert nach Priorität.
  4. Verbindliche Regel: Jeder Handler ruft ausschließlich Methoden der TodoList auf und zeichnet danach über eine einzige Methode refresh_view() neu. Kein Handler hält eigene Aufgabendaten.
  1. Nichts darf crashen: leerer Text, “Done” ohne Auswahl, hektische Doppelklicks. ValueError aus der Logik wird im Handler gefangen und als messagebox.showwarning mit verständlichem Text gemeldet.
  2. Beim Schließen des Fensters wird die Liste als JSON gespeichert, beim Start wieder geladen (recherchieren Sie root.protocol("WM_DELETE_WINDOW", ...)). Eine fehlende Datei bedeutet: leere Liste; eine kaputte Datei führt zu einer Meldung und einem Neustart mit leerer Liste, nicht zum Absturz.
  3. Härtetest durch die Sitznachbarin oder den Sitznachbarn: fünf Minuten freies Bedienen. Protokollieren Sie gefundene Probleme und beheben Sie sie.
  1. Kapseln Sie die Aufgabenliste als eigene Widget-Klasse TaskListPanel(tk.Frame) mit den Methoden refresh(tasks) und get_selected_index(). Das Hauptfenster spricht nur noch mit dem Panel, nicht mehr mit der Listbox direkt.
  2. Ergänzen Sie einen Filter (alle / nur Priorität 1) als Zustand des Panels, ohne die TodoList-Klasse zu verändern. Begründen Sie in zwei Sätzen, warum der Filter in die Ansicht gehört und nicht in die Fachlogik.
  3. Ergänzen Sie Tastaturkomfort mit bind: Eingabetaste fügt hinzu, Entf löscht den ausgewählten Eintrag.
  4. Architektur-Nachweis: Führen Sie pytest aus, während die GUI-Datei gar nicht importierbar wäre (benennen Sie sie testweise um). Die Logik-Tests müssen unverändert laufen. Erklären Sie in drei Sätzen, was dieser Nachweis über Ihre Schichtentrennung beweist und warum das für Teamarbeit zählt.
  1. Was ist die Ereignisschleife, und warum steht nach mainloop() kein weiterer Programmcode?
  2. Warum muss es command=self.on_add heißen und nicht command=self.on_add()?
  3. Wo wird ein ValueError aus der Fachlogik gefangen, und warum genau dort?
  4. Warum bleibt eine GUI-freie Logikklasse testbar, eine mit eingebauten messagebox-Aufrufen aber nicht?
  5. Was gehört in refresh_view(), und warum darf Anzeigezustand nirgendwo sonst gepflegt werden?

todo_logic.py, todo_gui.py, test_todo.py und die gespeicherte JSON-Datei, als Git-Repository mit nachvollziehbarer Historie (mindestens fünf thematisch getrennte Commits); dazu das Härtetest-Protokoll.