# -*- coding: utf-8 -*- """Icons aus dem Hub-Vorrat (Material Symbols), eingefaerbt zur Laufzeit. Die SVGs liegen auf dem Hub (`M:/projekte/material-symbols`) und wurden einmal nach PNG gewandelt - als weisse Silhouette mit Transparenz. Hier bekommen sie ihre Farbe: dieselbe Datei taugt fuer die Akzentfarbe, fuer gedaempfte Schrift und fuer das helle Thema, ohne dass jemand drei Fassungen pflegt. Ohne Pillow oder ohne Datei gibt es einfach kein Bild zurueck - der Aufrufer zeigt dann seinen Text. Ein fehlendes Icon darf kein Fenster verhindern. """ import os import tkinter as tk import config # ⚠️ Ein PhotoImage gehoert zu GENAU EINEM Tk-Fenster. Wird ein zweites # aufgemacht (ein Pruefstand faehrt Journal und Rechnungstool nacheinander), # zeigt ein weitergereichtes Bild ins Leere: 'image "pyimage1" doesn't exist'. # Deshalb steht das Fenster mit im Schluessel. _zwischenlager = {} # (fenster, name, groesse, farbe) -> PhotoImage def _pfad(name): for basis in (config.BASE_DIR, config.RESOURCE_DIR, os.path.dirname(os.path.abspath(__file__))): p = os.path.join(basis, "assets", "icons", name + ".png") if os.path.exists(p): return p return "" def hole(name, groesse=18, farbe="#e8e8ea", master=None): """Icon als PhotoImage - oder None, wenn es nicht geht. `master` ist das Widget, in dem das Bild landet. Es MUSS mitgegeben werden, wenn mehr als ein Tk-Fenster laeuft: `tk._default_root` zeigt dann auf das zuerst geoeffnete, und das Bild gehoert dem falschen Fenster. """ fenster = master if master is not None else tk._default_root if fenster is None: return None schluessel = (id(fenster), name, groesse, farbe) if schluessel in _zwischenlager: return _zwischenlager[schluessel] pfad = _pfad(name) if not pfad: print(f"[icons] nicht gefunden: {name}") return None try: from PIL import Image, ImageTk bild = Image.open(pfad).convert("RGBA") bild = bild.resize((groesse, groesse), Image.LANCZOS) # Die Silhouette steckt im Alphakanal - die Farbe kommt hier drueber. flaeche = Image.new("RGBA", bild.size, farbe) flaeche.putalpha(bild.getchannel("A")) fertig = ImageTk.PhotoImage(flaeche, master=fenster) except Exception as e: # noqa: BLE001 - ein Icon darf nichts blockieren print(f"[icons] {name} nicht ladbar: {e}") return None _zwischenlager[schluessel] = fertig return fertig