# -*- coding: utf-8 -*- """Pruefstand: hell, dunkel, automatisch - und nichts geht dabei verloren. Sein Wortlaut vom 07.09.2026: "waere nun noch gut das mann in den einstellungen einstellen kann hell oder dunkel oder automatik das fehlt sollte eigendlich drin sein" GEPRUEFT WIRD DREIERLEI 1. Die Einstellung wirkt. "hell" ist hell, "dunkel" ist dunkel, "auto" folgt Windows. 2. Beim Umschalten bleibt jede Eingabe stehen. Das ist der Punkt, an dem es beim Bauen schiefging: die Mengen der Leistungszeilen hatte ich einzeln gesichert, Kundenname und Rechnungsnummer nicht - die _build_-Methoden legen ihre Variablen selbst an, beim Neubau standen also leere da. Wer waehrend einer halb getippten Rechnung auf dunkel stellt, darf sie nicht verlieren. 3. NACH dem Wechsel traegt kein Widget mehr eine Farbe der anderen Palette. Das ist die eigentliche Falle beim Umfaerben: ein einzelnes vergessenes Label leuchtet hell im dunklen Fenster, und niemand findet die Stelle wieder. Deshalb wird der ganze Widget-Baum abgegangen und mit den Farben der jeweils ANDEREN Palette verglichen. """ import json import os import shutil import sys import tempfile import time import tkinter as tk QUELLE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, QUELLE) fehler = [] def pruefe(bedingung, text): zeile = (" OK | " if bedingung else "FEHLER | ") + text kod = sys.stdout.encoding or "utf-8" print(zeile.encode(kod, "replace").decode(kod)) if not bedingung: fehler.append(text) os.chdir(QUELLE) os.environ["CAMPINGHOF_TEST"] = "1" from tkinter import messagebox # noqa: E402 messagebox.askyesno = lambda *a, **k: True for _n in ("showinfo", "showwarning", "showerror"): setattr(messagebox, _n, lambda *a, **k: None) import config # noqa: E402 # Auf einer Kopie arbeiten - die echte Konfiguration wird nicht angefasst. tmp = tempfile.mkdtemp(prefix="darstellung_") shutil.copy(os.path.join(QUELLE, "config.json"), os.path.join(tmp, "config.json")) config.CONFIG_PATH = os.path.join(tmp, "config.json") roh = json.load(open(config.CONFIG_PATH, encoding="utf-8")) roh["nummer_eingerichtet"] = True roh.pop("darstellung", None) json.dump(roh, open(config.CONFIG_PATH, "w", encoding="utf-8"), ensure_ascii=False, indent=2) import app as A # noqa: E402 import theme # noqa: E402 f = A.RechnungsApp() def pumpen(sekunden=1.0): ende = time.time() + sekunden while time.time() < ende: f.update() time.sleep(0.02) pumpen(2.0) # ---- Ohne Einstellung: automatisch -------------------------------------- pruefe(theme.modus(f.cfg) == "auto", f"ohne Eintrag gilt 'auto' ({theme.modus(f.cfg)!r})") pruefe(f._dark_mode == theme.windows_dark_mode(), "und folgt damit dem Windows-Theme") # ---- Eingaben, die den Wechsel ueberleben muessen ------------------------ f.k_vorname.set("Erika") f.k_name.set("Mustermann") f.k_strasse.set("Musterweg 12") f.k_plzort.set("04416 Markkleeberg") f.r_nummer.set("2026-099") f.r_anreise.set("01.09.2026") erste = sorted(f.anzahl_vars)[0] f.anzahl_vars[erste].set("3") pumpen(0.5) def farben(dunkel): """Die Palette der einen oder anderen Darstellung, als Menge.""" merker = f._dark_mode f.cfg["darstellung"] = "dunkel" if dunkel else "hell" f._apply_theme() satz = {getattr(f, n).lower() for n in dir(f) if n.startswith("col_") and isinstance(getattr(f, n), str)} f._dark_mode = merker return satz HELL = farben(False) DUNKEL = farben(True) # Was in BEIDEN Paletten vorkommt, taugt nicht als Beweis. NUR_HELL = HELL - DUNKEL NUR_DUNKEL = DUNKEL - HELL def fremdfarben(verboten): """Alle Widgets, die eine Farbe der falschen Palette tragen.""" treffer = [] def durchgehen(w): for kind in w.winfo_children(): for eigenschaft in ("bg", "background", "fg", "foreground"): try: wert = str(kind.cget(eigenschaft)).lower() except tk.TclError: continue if wert in verboten: treffer.append((str(kind), eigenschaft, wert)) durchgehen(kind) durchgehen(f) return treffer # ---- Die drei Modi ------------------------------------------------------ for wunsch, soll_dunkel in (("hell", False), ("dunkel", True)): f.cfg["darstellung"] = wunsch config.save_config(f.cfg) f._oberflaeche_neu() pumpen(0.8) pruefe(f._dark_mode == soll_dunkel, f"'{wunsch}' zeichnet {'dunkel' if soll_dunkel else 'hell'} " f"(Hintergrund {f.col_bg})") # Nichts darf verlorengehen. pruefe(f.k_name.get() == "Mustermann", f"nach dem Wechsel steht der Kundenname noch da ({f.k_name.get()!r})") pruefe(f.r_nummer.get() == "2026-099", f"und die Rechnungsnummer ({f.r_nummer.get()!r})") pruefe(f.k_plzort.get() == "04416 Markkleeberg", f"und die Anschrift ({f.k_plzort.get()!r})") pruefe(f.r_anreise.get() == "01.09.2026", f"und das Anreisedatum ({f.r_anreise.get()!r})") pruefe(f.anzahl_vars.get(erste) is not None and f.anzahl_vars[erste].get() == "3", "und die eingetragene Menge in der Leistungszeile") # Kein Rest der anderen Palette. reste = fremdfarben(NUR_DUNKEL if not soll_dunkel else NUR_HELL) pruefe(not reste, f"in '{wunsch}' ist keine Farbe der anderen Darstellung " f"uebrig ({reste[:3]})") # ---- Zurueck auf automatisch -------------------------------------------- f.cfg["darstellung"] = "auto" config.save_config(f.cfg) f._oberflaeche_neu() pumpen(0.8) pruefe(f._dark_mode == theme.windows_dark_mode(), "'auto' folgt wieder dem Windows-Theme") # ---- Und die Einstellung ueberlebt den Neustart ------------------------- f.cfg["darstellung"] = "hell" config.save_config(f.cfg) f.destroy() f = A.RechnungsApp() pumpen(2.0) pruefe(f._dark_mode is False, "die Einstellung steht beim naechsten Start wieder da") try: f.destroy() except Exception: # noqa: BLE001 pass shutil.rmtree(tmp, ignore_errors=True) if fehler: print(f"ROT | {len(fehler)} Punkt(e) nicht erfuellt") sys.exit(1) print("GRUEN | Hell, dunkel und automatisch wirken - ohne Datenverlust")