晨曦的宇宙
首页项目归档照片墙音乐灵境说说杂谈友链关于
封面

PiManager:自建 Pillow UI 组件库

写作时间:2026-06-19
# Python
# Pillow
# 开源

一个 SSH 管理器,2000 行 UI 重写,13 个自研组件,37 个渲染 bug。MIT 开源。

为什么重写

PiManager 最初用 CustomTkinter 写桌面 SSH 客户端。暗色主题、侧边栏导航、四个功能页(状态监控/文件管理/终端/设置)。用着还行,但有两个问题:

  1. CTk 的渲染管线和天气站的 Pillow 图层风格不一致——同一套代码仓里跑两种 UI 范式,格格不入
  2. CTk 的定制能力有限——想加 hover 渐变、圆角卡片阴影,要么 hack CTk 源码,要么放弃

于是决定:把全部 CTk 渲染层换成 Pillow + tkinter Canvas,自建组件库。

pillui:13 个组件

所有组件继承 BaseComponent,核心方法就四个:

  • draw(cw, ch, font_scale):返回 PIL RGBA 图层
  • hit_test(mx, my):鼠标在组件上吗
  • on_click():点击事件回调
  • on_drag():拖拽事件回调

渲染管线:每个组件画一层 RGBA → Image.alpha_composite() 叠加 → ImageTk.PhotoImage → 一次性贴到 Canvas。

组件清单:

  • PillowButton:hover/pressed 三态切换 + 圆角 + 禁用态
  • PillowLabel:多行文字 + 左/中/右对齐 + 粗体
  • PillowCard:圆角容器 + 标题栏 + 边框
  • PillowProgressBar:圆角轨道 + 渐变填充
  • PillowSlider:拖拽交互 + 步进值
  • PillowCheckBox:方框 + 勾号 + BooleanVar 绑定
  • PillowOptionMenu:Pillow 显示面 + 弹出原生 tk.Menu
  • PillowScrollFrame:PageCanvas 子类 + 垂直滚动

37 个渲染 bug

代码写出来了,跑起来才发现 Pillow 渲染暗坑巨多。

文字周围暗色小框

症状:所有按钮上的文字边缘有灰色方框。

根因:PIL 的 ImageDraw.text() 在透明 RGBA 层上绘字时,抗锯齿的边缘像素与透明黑混合,产生暗色晕轮。

修复:把文字画在实色背景层上(和组件自身填充色一致),再合成到透明层。

亮色主题整个页面变黑

症状:点了"浅色模式"后所有卡片、标签、按钮全部黑色。

根因:所有组件在 init 时把颜色写死在实例属性里。refresh_theme() 只改了 Canvas 背景色——组件颜色根本没动。

修复:给每个组件加 apply_theme() 方法,从 ThemeColors 动态重读颜色令牌。切主题时 PageCanvas 遍历所有组件调 apply_theme()。

设置页只见最后一张卡片

症状:设置页只显示"关于"卡片,前面三张全消失。

根因:修复"文字小框"时把 create_layer 改成了 create_text_layer。后者创建的是全画布尺寸的不透明层。alpha_composite() 逐层叠加时,每张卡片的全画布不透明层把前面所有内容全部覆盖。

修复:PillowCard 和 PillowOptionMenu 改回透明层——它们在 draw() 里已经画了自己的圆角矩形填充。

emoji 全变豆腐块

症状:标题里的图标全部渲染为方框。

根因:Pillow 没有字体回退。msyh.ttc 没有 emoji 字形,PIL 不会自动找 Segoe UI Emoji。

修复:38 个 emoji 全部替换为纯文字。

IP 漂移自动修复

树莓派 DHCP 换 IP 后 SSH 连接断开——这是日常问题。

第一版(v2.2.0):功能写了,不好用

加了 socket.getaddrinfo() 重解析 + 指数退避重连。但上线后发现四个缺陷:

  1. 主机名被解析后的 IP 覆盖——漂移修复只生效一次
  2. Keep-alive 从未启动——断线根本检测不到
  3. 重连耗尽后 UI 仍显示"已连接"——用户以为还连着
  4. Keep-alive 双重触发重连——浪费重试配额

第二版(v2.2.2):意外的连接杀手

更致命的是:keep-alive 每 30 秒探测一次,单次超时就触发自动重连,而 connect() 第一步是 disconnect()——瞬态超时把健康连接杀死了。

修复:exec_command 不再触发自动重连;keep-alive 连续 2 次失败才重连。

开源

2026 年 6 月 19 日,MIT 协议发布:

  • 13 个 pillui 组件,零外部 UI 依赖
  • 261 单元测试,全部通过
  • 5 份文档:README + 架构文档 + API 参考 + 用户指南 + 合规报告
  • 跨平台:paramiko + Pillow + tkinter,Python 3.9+ 即可运行

技术栈

  • UI 渲染:Pillow + tkinter Canvas(和天气站统一风格)
  • 组件库:自建 pillui(13 文件)
  • SSH:paramiko(Python 标准 SSH 库)
  • 主题:ThemeColors 类(暗/亮双模式 + 三套强调色)
  • 测试:unittest(标准库,零依赖)
avatar

晨曦

你好,我是晨曦。是一个高中生,没事喜欢用AI让自己的项目落地。

RECOMMENDED

智能天气钟表

2025-09-09

树莓派智能驾驶小车

2025-06-09

个人网站迭代记录

2026-08-09

Table of Contents