Swing UI 开发准备地图¶
本文档用于给 TG-FF 的 Java Swing UI 调整做快速对齐,重点是:
- 现有 Swing 结构在哪些文件
- 主题、标题栏、弹窗、加载态分别怎么接入
- 调整 UI 时哪些地方优先动,哪些地方要谨慎
当前技术基线¶
- 构建:Maven
- Java:21
- Look and Feel:FlatLaf 3.7
- 主界面容器:Swing
JFrame - 主内容区:JCEF 浏览器组件
- UI 形态:
Swing 外壳 + 自定义标题栏 + JCEF 页面
这意味着我们现在要调整的不是传统“纯 Swing 后台管理系统”,而是一个带原生窗口定制、重度嵌入浏览器组件的桌面壳层。
关键入口文件¶
启动与全局主题¶
src/main/java/b/Launcher.java
职责:
- 启动时调用
setupFlatLaf() - 先显示
SplashScreen - 后台初始化
CefAppManager、App - 隐式初始化
MainFrame - 等待首屏资源和前端 ready 后再显示主窗口
关键信息:
- macOS 使用
FlatMacLightLaf - Windows/Linux 使用
FlatIntelliJLaf - 全局抗锯齿和字体渲染在这里设置
如果要做全局视觉基调调整,优先从这里看主题初始化是否要补全统一 token 或全局 UIManager 配置。
主窗口壳层¶
src/main/java/b/MainFrame.java
职责:
- 创建主
JFrame - 配置 Java 标题栏窗口属性
- 将
MainFrameTitleBar和 JCEF 内容区拼装到一起 - 管理窗口尺寸、显示、焦点、托盘、标题栏数据同步
当前主窗口结构大致是:
JFrame -> resizeLayer -> contentPanel -> [MainFrameTitleBar + browserHolder(JCEF)]
当前窗口约束:
- 默认尺寸:
1336 x 900 - 最小尺寸:
1300 x 850 - 最大尺寸:
1336 x 1000
如果后面我们改整体布局、边距、窗口气质,这里会是第一落点。
自定义标题栏¶
src/main/java/b/ui/MainFrameTitleBar.java
职责:
- 自定义标题栏 UI
- 顶部状态胶囊:会员、代理、网络、上传下载速率
- 主题切换后的颜色重绘
- 标题栏交互事件回传给前端
- macOS/Windows 不同标题栏行为适配
当前特点:
- 高度常量:
42 - 内置
LIGHT_THEME/DARK_THEME - 颜色目前主要是代码里硬编码的 palette
- 交互通过
ActionPayload回给前端桥
如果这轮改造是“更现代、更统一、更高级”的标题栏,这个文件会是最高优先级。
启动页¶
src/main/java/b/ui/SplashScreen.java
职责:
- 启动渐变背景页
- 图标、标题、状态文本、进度条
- 启动期错误展示
当前特点:
- 视觉是偏浅蓝渐变
- 进度条和文案已做过定制
- 主要用于启动阶段,不参与主界面日常交互
如果本轮 UI 只聚焦主界面,这里优先级低于标题栏和弹窗。
全局加载遮罩¶
src/main/java/b/ui/GlobalLoading.java
职责:
- 给
JFrame/JDialog/Window提供 loading 遮罩 - 兼容 JCEF 这种 heavyweight 组件
关键点:
- 普通场景走
glassPane - 对
Window场景可走透明JDialog叠层,避免被 JCEF 压住 - 视觉由半透明蒙层 + 中央 spinner + pill 文案组成
这个文件是后续统一“加载态风格”的重要位置。
次级 UI 入口¶
通用浏览器弹窗¶
src/main/java/b/ui/JcefBrowserDialog.java
用途:
- 可复用的
JDialog + JCEF - 登录、抓取、辅助操作类弹窗都可能复用它
如果我们想统一弹窗边距、圆角、标题、默认尺寸、遮罩体验,这里值得单独整理。
M3U8 相关弹窗动作¶
src/main/java/b/ui/OpenM3u8DialogAction.java
特点:
- 通过
JcefBrowserDialog打开流程型弹窗 - 偏功能逻辑驱动,但会影响弹窗行为和交互体验
Cookie 登录窗口¶
src/main/java/b/ui/OpenGetCookieWindowAction.java
特点:
- 内部有一个
BrowserFrame extends JFrame - 属于独立窗口,不完全走主框架壳层
这类窗口后面如果要统一风格,最好收敛到统一弹窗/窗口基类策略。
系统托盘¶
src/main/java/b/ui/SystemTrayManager.java
虽然不是核心视觉区,但它影响窗口可见性、最小化、退出路径。涉及窗口行为时要一起确认。
现成可参考的 UI Demo¶
src/test/java/b/test/FlatLafCustomTitleDemo.javasrc/test/java/b/test/LoadingDemo.javasrc/test/java/b/test/LafTest.java
用途:
- 快速验证标题栏布局方案
- 快速验证 loading 视觉效果
- 快速验证 FlatLaf 配置是否符合预期
如果我们要尝试新的标题栏布局或 loading 细节,建议先在这些 demo 上验证,再合进主代码。
现有 UI 改造优先级¶
建议按照下面顺序推进:
MainFrameTitleBarMainFrameGlobalLoadingJcefBrowserDialog/ 登录类弹窗SplashScreen
原因:
- 标题栏最能直接拉高整体质感
- 主窗口边距和层级决定整体观感
- loading 和弹窗会决定“完成度”
- 启动页影响相对次要
当前 UI 机制里的几个关键限制¶
1. JCEF 是 heavyweight 组件¶
这会带来两个直接影响:
- 普通 Swing 叠层不一定能盖住它
- 遮罩、弹窗、拖拽、焦点处理都要更小心
因此:
- 遮罩相关优先沿用
GlobalLoading现有思路 - 不要想当然把普通
JPanel盖在浏览器上就结束
2. 主题并没有完全 token 化¶
当前标题栏颜色主要集中在 MainFrameTitleBar 内部静态 palette,其他地方也有各自硬编码颜色。
这意味着:
- 小改可以直接改局部 palette
- 如果要做系统级统一风格,建议抽一层 Swing 主题 token
3. 标题栏不只是视觉组件¶
MainFrameTitleBar 同时承担:
- 状态展示
- 按钮交互
- 与前端桥通信
- 窗口 caption / drag 区域控制
所以改它时不能只看样式,还要保住:
- 拖拽区域
- macOS 按钮占位
- Windows 标题栏属性同步
- 事件锚点坐标回传
4. 跨平台差异已经存在¶
现在代码已经显式区分:
- macOS 标题栏属性
- Windows/Linux 的 FlatLaf window decorations
- 托盘在 macOS 默认关闭
所以 UI 修改要默认带着“至少 macOS + Windows”两个维度思考。
建议的本轮改造方法¶
第一阶段:统一视觉语言¶
建议先统一这些基础项:
- 标题栏高度、内边距、间距
- 主色、文字色、弱化色、状态色
- 胶囊圆角、边框、阴影
- 图标尺寸和按钮 hit area
- loading 遮罩透明度和文案样式
第二阶段:统一窗口与弹窗风格¶
建议处理:
- 主窗口边距与内容留白
- JDialog/JFrame 弹窗默认尺寸和位置策略
- 浏览器弹窗标题和关闭体验
- 登录/抓取窗口是否需要统一外壳
第三阶段:整理代码结构¶
当视觉稳定后,可以再考虑:
- 抽
SwingThemeTokens - 抽通用
Pill/IconButton/StatusDot - 收敛重复颜色和尺寸常量
- 收敛弹窗基类或窗口配置工具
实战时建议先看的文件组合¶
如果下一步直接开始改标题栏:
src/main/java/b/ui/MainFrameTitleBar.javasrc/main/java/b/MainFrame.javasrc/test/java/b/test/FlatLafCustomTitleDemo.java
如果下一步改加载态:
src/main/java/b/ui/GlobalLoading.javasrc/test/java/b/test/LoadingDemo.java
如果下一步改启动页:
src/main/java/b/ui/SplashScreen.javasrc/main/java/b/Launcher.java
如果下一步改弹窗体系:
src/main/java/b/ui/JcefBrowserDialog.javasrc/main/java/b/ui/OpenGetCookieWindowAction.javasrc/main/java/b/ui/OpenM3u8DialogAction.java
我们接下来可以直接怎么做¶
推荐从下面三种方式里选一种进入:
- 直接重做
MainFrameTitleBar的布局和视觉 - 先统一
GlobalLoading + JcefBrowserDialog的弹窗和遮罩风格 - 先抽一层 Swing 设计 token,再逐个替换现有硬编码颜色和尺寸
如果目标是最快看到成品效果,建议先从 MainFrameTitleBar 开始。