Files
Your Name 47c6589e1d feat: application icon for Windows taskbar + exe
- scripts/gen_icon.py: generates 256x256 SSH client icon (dark terminal
  window with >_ prompt and SSH connection nodes), outputs multi-size
  ICO (16-256px) + PNG
- resources/icon.ico + icon.png: generated icon files
- main.py: _get_icon_path() searches _MEIPASS (onefile), exe dir, source
  dir; sets app + window icon
- build.spec: bundles icon files via datas=, sets exe icon=icon.ico
- Windows taskbar will now show the custom icon instead of default PyInstaller icon
2026-07-29 06:54:12 +08:00

131 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
生成 SSHClient 应用图标
- 深色圆角方块背景
- 终端窗口 + >_ 提示符 + SSH 连接线
输出: resources/icon.ico (多尺寸) + resources/icon.png (256x256)
"""
import os
from PIL import Image, ImageDraw, ImageFont
OUT_DIR = os.path.join(os.path.dirname(__file__), "resources")
os.makedirs(OUT_DIR, exist_ok=True)
SIZE = 256
def draw_icon(size: int) -> Image.Image:
"""绘制指定尺寸的图标"""
img = Image.new("RGBA", (size, size), (0, 0, 0, 0))
d = ImageDraw.Draw(img)
pad = int(size * 0.06)
rect = [pad, pad, size - pad, size - pad]
radius = int(size * 0.18)
# 背景渐变(模拟,用两层半透明)
d.rounded_rectangle(rect, radius=radius, fill=(30, 30, 46, 255))
# 上半部分亮色渐变
inner = [pad + 4, pad + 4, size - pad - 4, size // 2]
d.rounded_rectangle(inner, radius=radius - 2, fill=(40, 40, 60, 255))
# 终端窗口
tw_margin = int(size * 0.16)
tw_top = int(size * 0.20)
tw_bottom = int(size * 0.78)
tw_left = tw_margin
tw_right = size - tw_margin
tw_radius = int(size * 0.04)
# 终端窗口阴影
shadow_offset = max(2, size // 64)
d.rounded_rectangle(
[tw_left + shadow_offset, tw_top + shadow_offset,
tw_right + shadow_offset, tw_bottom + shadow_offset],
radius=tw_radius, fill=(0, 0, 0, 60)
)
# 终端窗口背景
d.rounded_rectangle(
[tw_left, tw_top, tw_right, tw_bottom],
radius=tw_radius, fill=(12, 12, 20, 255)
)
# 终端标题栏
tb_height = int(size * 0.055)
d.rounded_rectangle(
[tw_left, tw_top, tw_right, tw_top + tb_height],
radius=tw_radius, fill=(50, 50, 70, 255)
)
# 底部直角覆盖(标题栏只有上面圆角)
d.rectangle(
[tw_left, tw_top + tb_height - tw_radius, tw_right, tw_top + tb_height],
fill=(50, 50, 70, 255)
)
# 三个小圆点(macOS 风格窗口按钮)
dot_r = max(2, int(size * 0.016))
dot_y = tw_top + tb_height // 2
dot_start = tw_left + int(size * 0.04)
dot_gap = int(size * 0.045)
for i, color in enumerate([(239, 83, 80), (255, 167, 38), (102, 187, 106)]):
cx = dot_start + i * dot_gap
d.ellipse([cx - dot_r, dot_y - dot_r, cx + dot_r, dot_y + dot_r], fill=color)
# >_ 提示符
cx = tw_left + int(size * 0.06)
cy = tw_top + tb_height + int(size * 0.10)
line_w = max(2, int(size * 0.022))
arrow_len = int(size * 0.08)
gap = int(size * 0.02)
# > 符号
d.line([cx, cy, cx + arrow_len, cy + arrow_len // 2],
fill=(102, 187, 106), width=line_w)
d.line([cx, cy + arrow_len, cx + arrow_len, cy + arrow_len // 2],
fill=(102, 187, 106), width=line_w)
# _ 光标
cursor_x = cx + arrow_len + gap
cursor_w = int(size * 0.06)
cursor_h = max(2, int(size * 0.018))
d.rounded_rectangle(
[cursor_x, cy + arrow_len // 2 - cursor_h // 2,
cursor_x + cursor_w, cy + arrow_len // 2 + cursor_h // 2],
radius=max(1, cursor_h // 3), fill=(137, 180, 250)
)
# SSH 连接线(底部装饰)
line_y = tw_bottom + int(size * 0.05)
if line_y < size - pad:
# 连接节点
node_r = max(2, int(size * 0.012))
n1 = (tw_left + int(size * 0.04), line_y)
n2 = (tw_right - int(size * 0.04), line_y)
d.ellipse([n1[0]-node_r, n1[1]-node_r, n1[0]+node_r, n1[1]+node_r],
fill=(137, 180, 250))
d.ellipse([n2[0]-node_r, n2[1]-node_r, n2[0]+node_r, n2[1]+node_r],
fill=(137, 180, 250))
d.line([n1[0]+node_r, n1[1], n2[0]-node_r, n2[1]],
fill=(137, 180, 250, 160), width=max(1, line_w // 2))
return img
def main():
# 生成 256x256 主图
icon = draw_icon(SIZE)
png_path = os.path.join(OUT_DIR, "icon.png")
icon.save(png_path)
print(f"Saved {png_path} ({SIZE}x{SIZE})")
# 生成多尺寸 ICOPillow 自动从 256x256 缩放到各尺寸)
sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
ico_path = os.path.join(OUT_DIR, "icon.ico")
icon.save(ico_path, format="ICO", sizes=sizes)
print(f"Saved {ico_path} (sizes: {[s[0] for s in sizes]})")
print("Done!")
if __name__ == "__main__":
main()