Modernes Design: neue Symbole und Programm-Icon, ohne „95“ im Namen, Tipp des Tages ohne Büroklammer
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
851fd6600a
commit
8c86571034
35 files changed
+149
-43
No files matched your search
@@ -0,0 +1,117 @@
|
||||
"""Zeichnet die modernen Symbole (flach, wie Windows 11) und das Programm-Icon.
|
||||
|
||||
Ausgabe: provtool/gui/bilder/modern/<name>.png (20 px) und <name>_gross.png (40 px),
|
||||
assets/app.ico und assets/app.png. Benötigt Pillow – nur zum Entwickeln, nicht zur Laufzeit.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
ZIEL = ROOT / "provtool" / "gui" / "bilder" / "modern"
|
||||
N = 160 # Zeichenfläche (8-fach), danach weich verkleinert
|
||||
LINIE, AKZENT, HELL = (66, 66, 66, 255), (0, 95, 184, 255), (255, 255, 255, 255)
|
||||
GELB, ROT, ORANGE = (240, 190, 70, 255), (196, 43, 28, 255), (247, 168, 0, 255)
|
||||
S = 9 # Strichstärke auf der Zeichenfläche
|
||||
SCHRIFT = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
|
||||
|
||||
|
||||
def leinwand():
|
||||
img = Image.new("RGBA", (N, N), (0, 0, 0, 0))
|
||||
return img, ImageDraw.Draw(img)
|
||||
|
||||
|
||||
def zeichen(d, text, farbe, groesse=104):
|
||||
f = ImageFont.truetype(SCHRIFT, groesse)
|
||||
d.text((N / 2, N / 2 + 4), text, font=f, fill=farbe, anchor="mm")
|
||||
|
||||
|
||||
def prozent(d, farbe, s=S):
|
||||
d.ellipse((28, 28, 68, 68), outline=farbe, width=s)
|
||||
d.ellipse((92, 92, 132, 132), outline=farbe, width=s)
|
||||
d.line((120, 30, 40, 130), fill=farbe, width=s + 2)
|
||||
|
||||
|
||||
def neu(d):
|
||||
d.polygon([(34, 14), (96, 14), (126, 44), (126, 146), (34, 146)], outline=LINIE, width=S, fill=HELL)
|
||||
d.line([(96, 14), (96, 44), (126, 44)], fill=LINIE, width=S)
|
||||
d.ellipse((86, 86, 150, 150), fill=AKZENT)
|
||||
d.line((118, 100, 118, 136), fill=HELL, width=S)
|
||||
d.line((100, 118, 136, 118), fill=HELL, width=S)
|
||||
|
||||
|
||||
def oeffnen(d):
|
||||
d.polygon([(14, 34), (62, 34), (76, 50), (146, 50), (146, 132), (14, 132)], fill=GELB, outline=(193, 140, 30, 255),
|
||||
width=S - 2)
|
||||
d.rectangle((14, 66, 146, 132), fill=(250, 210, 100, 255), outline=(193, 140, 30, 255), width=S - 2)
|
||||
|
||||
|
||||
def ablage(d, hoch: bool):
|
||||
d.line([(18, 96), (18, 140), (142, 140), (142, 96)], fill=LINIE, width=S, joint="curve")
|
||||
oben, unten = (14, 104) if hoch else (14, 104)
|
||||
d.line((80, oben, 80, unten), fill=AKZENT, width=S + 2)
|
||||
if hoch:
|
||||
d.polygon([(80, 8), (52, 42), (108, 42)], fill=AKZENT)
|
||||
else:
|
||||
d.polygon([(80, 118), (52, 82), (108, 82)], fill=AKZENT)
|
||||
|
||||
|
||||
def haendler(d):
|
||||
d.ellipse((24, 26, 74, 76), outline=LINIE, width=S)
|
||||
d.arc((8, 82, 90, 170), 180, 360, fill=LINIE, width=S)
|
||||
d.ellipse((88, 34, 132, 78), fill=AKZENT)
|
||||
d.pieslice((74, 86, 152, 166), 180, 360, fill=AKZENT)
|
||||
|
||||
|
||||
def rechner(d): # Stift: Betrag ändern
|
||||
d.polygon([(110, 18), (142, 50), (58, 134), (26, 102)], fill=HELL, outline=LINIE, width=S)
|
||||
d.polygon([(26, 102), (58, 134), (16, 144)], fill=AKZENT)
|
||||
d.line((98, 30, 130, 62), fill=LINIE, width=S)
|
||||
|
||||
|
||||
def birne(d):
|
||||
d.ellipse((34, 10, 126, 102), fill=GELB, outline=(193, 140, 30, 255), width=S - 2)
|
||||
d.rectangle((56, 96, 104, 122), fill=GELB)
|
||||
d.rectangle((56, 122, 104, 150), fill=(120, 120, 120, 255))
|
||||
d.line((60, 134, 100, 134), fill=HELL, width=4)
|
||||
|
||||
|
||||
def kreis(d, farbe, text):
|
||||
d.ellipse((6, 6, 154, 154), fill=farbe)
|
||||
zeichen(d, text, HELL)
|
||||
|
||||
|
||||
def warnung(d):
|
||||
d.polygon([(80, 8), (156, 148), (4, 148)], fill=ORANGE)
|
||||
zeichen(d, "!", (30, 30, 30, 255), 92)
|
||||
|
||||
|
||||
def app(d):
|
||||
d.rounded_rectangle((4, 4, 156, 156), radius=34, fill=AKZENT)
|
||||
prozent(d, HELL, 13)
|
||||
|
||||
|
||||
ICONS = {
|
||||
"neu": neu, "oeffnen": oeffnen, "import": lambda d: ablage(d, False), "export": lambda d: ablage(d, True),
|
||||
"haendler": haendler, "prozent": lambda d: prozent(d, AKZENT), "rechner": rechner, "birne": birne,
|
||||
"info": lambda d: kreis(d, AKZENT, "i"), "frage": lambda d: kreis(d, AKZENT, "?"),
|
||||
"fehler": lambda d: kreis(d, ROT, "×"), "warnung": warnung, "app": app,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
ZIEL.mkdir(parents=True, exist_ok=True)
|
||||
for name, zeichne in ICONS.items():
|
||||
img, d = leinwand()
|
||||
zeichne(d)
|
||||
img.resize((20, 20), Image.LANCZOS).save(ZIEL / f"{name}.png")
|
||||
img.resize((40, 40), Image.LANCZOS).save(ZIEL / f"{name}_gross.png")
|
||||
if name == "app":
|
||||
gross = img.resize((256, 256), Image.LANCZOS)
|
||||
gross.save(ROOT / "assets" / "app.png")
|
||||
gross.save(ROOT / "assets" / "app.ico", sizes=[(s, s) for s in (16, 24, 32, 48, 64, 128, 256)])
|
||||
print(f"{len(ICONS)} Symbole nach {ZIEL} geschrieben, assets/app.ico + app.png erneuert")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user