用 Java 写出像 top/htop 这样的酷炫命令行界面?

张开发
2026/4/13 12:09:42 15 分钟阅读

分享文章

用 Java 写出像 top/htop 这样的酷炫命令行界面?
jink 开源框架做到了一个 Java 版的终端 UI 框架用声明式的方式构建带颜色、边框、动画的命令行应用。兼容 Java 8纯 Maven 依赖拿来即用。Gitee: https://gitee.com/free/jinkGitHub: https://github.com/abel533/jink它能做什么先看效果比解释更直观。下面这个类似top/htop的系统监控界面完全用 Java 写出来的实时 CPU 使用率进度条 颜色告警系统内存、JVM 堆、线程数进程列表支持排序和实时搜索鼠标滚轮滚动方向键导航选中行高亮还有这个控制台迷宫游戏加载中…随机 Prim 算法生成完美迷宫方向键移动绿色轨迹记录路径自适应终端尺寸这个框架叫jink是 inkReact for CLI的 Java 版实现。核心概念3 行代码理解它// 就像 React 一样Box divText spanInk.renderOnce(Box.of(Text.of(Hello, jink!).color(Color.GREEN).bold()).borderStyle(BorderStyle.ROUND).borderColor(Color.BRIGHT_MAGENTA).paddingX(1),40,5);输出╭──────────────────────────────────────╮ │ Hello, jink! │ ╰──────────────────────────────────────╯没有手写 ANSI 转义码没有坐标计算就像写 HTML 一样自然。它是怎么运作的整个渲染管道分 4 步组件树Box/Text ↓ 虚拟 DOMElementNode ↓ Flexbox 布局计算纯 Java 实现 ↓ VirtualScreen → ANSI 字符串 → 终端Flexbox 布局是纯 Java 实现的不依赖任何 native 库ink 用的是 Facebook 的 Yoga C 引擎。支持flexDirection、justifyContent、alignItems、flexGrow、gap、padding、margin和 CSS Flexbox 一脉相承。写一个有状态的交互组件类似 React 的useStateuseEffectpublicclassCounterextendsComponentCounter.State{// 状态定义用普通类或 record 都行staticclassState{finalintcount;State(intcount){this.countcount;}}publicCounter(){super(newState(0));}OverridepublicvoidonMount(){// 类比 useEffect组件挂载后启动定时器scheduler.scheduleAtFixedRate(()-{setState(newState(getState().count1));},100,100,TimeUnit.MILLISECONDS);}OverridepublicvoidonUnmount(){scheduler.shutdownNow();}OverridepublicRenderablerender(){returnText.of(getState().count tests passed).color(Color.GREEN);}}setState()触发重渲染框架自动做差量更新只刷新变化的行——和 React 的虚拟 DOM diff 思路一样。键盘交互重写onInput方法即可OverridepublicvoidonInput(Stringinput,Keykey){if(key.upArrow()){setState(newState(getState().selected-1));}elseif(key.downArrow()){setState(newState(getState().selected1));}elseif(q.equals(input)){System.exit(0);}}Key对象封装了方向键、功能键、Ctrl 组合键、PageUp/Down 等常用按键的判断方法不用再手动解析 ANSI 转义序列。样式系统丰富但不繁琐Text.of(粗体红色).bold().color(Color.RED)Text.of(RGB 真彩色).color(Color.rgb(255,165,0))Text.of(Hex 颜色).color(Color.hex(FF8800))Text.of(反色Inverse).inverse()Text.of(暗淡).dimmed()// 嵌套文本样式Text.of(Text.of(前缀 ).color(Color.CYAN),Text.of(高亮).color(Color.RED).bold(),Text.of( 后缀).dimmed())支持 16 色、256 色、RGB 真彩色中日韩字符自动占 2 列宽度。9 种边框样式┌──────┐ ╔══════╗ ╭─────╮ ┏━━━━┓ │single│ ║double║ │round│ ┃bold┃ └──────┘ ╚══════╝ ╰─────╯ ┗━━━━┛ ╓────────────╖ ╒════════════╕ ------- ↘↓↓↓↓↓↙ ║singleDouble║ │doubleSingle│ |classic| →arrow← ╙────────────╜ ╘════════════╛ ------- ↗↑↑↑↑↑↖Flexbox 布局写起来就像 CSS// 水平等分面板Box.of(Box.of(Text.of(左侧)).flexGrow(1).borderStyle(BorderStyle.SINGLE),Box.of(Text.of(右侧)).flexGrow(1).borderStyle(BorderStyle.SINGLE)).width(60).height(5);// 垂直布局 弹性填充Box.of(Text.of(标题).bold(),Spacer.create(),// 自动撑开中间空白Text.of(底部提示).dimmed()).flexDirection(FlexDirection.COLUMN).height(10);// 内容对齐Box.of(Text.of(X),Text.of(Y)).justifyContent(JustifyContent.SPACE_BETWEEN).width(20);// 输出[X Y]与 ink 的 API 对照功能ink (TypeScript)jink (Java)声明式 UIJSXBuilder API状态管理useStateComponent.setState()副作用useEffectonMount / onUnmount输入处理useInputonInput(String, Key)FlexboxYoga (C)纯 Java 实现颜色chalk内置Color边框boxen9 种BorderStyle最低版本Node.js 18Java 8开箱即用的 Demo 库项目自带 20 个 Demo覆盖各种使用场景Demo说明Counter自动递增计数器定时器 setStateTopDemo类 top/htop 系统监控 TUIMazeDemo控制台迷宫游戏Prim 算法CopilotDemoGitHub Copilot CLI 界面复刻FeatureShowcase4 个标签页综合展示SelectInputDemo方向键列表选择ChatDemo简单聊天输入框JestDemo并发测试运行器模拟一行命令运行任意 Demo.\scripts\run.ps1# 交互式菜单Windows./scripts/run.sh# 交互式菜单Linux/macOS快速上手1. 添加 Maven 依赖dependencygroupIdio.mybatis.jink/groupIdartifactIdjink/artifactIdversion0.5.0/version/dependency2. 写第一个组件publicclassHello{publicstaticvoidmain(String[]args){Ink.renderOnce(Box.of(Text.of(Hello, World!).color(Color.GREEN).bold()).borderStyle(BorderStyle.ROUND).paddingX(1),40,3);}}3. 或者用交互式渲染Ink.render(newMyComponent()).waitUntilExit();项目信息GitHubabel533/jinkLicenseApache 2.0Java 版本Java 8测试146 个单元测试当前版本0.5.0稳定发布如果你正在用 Java 构建 CLI 工具、DevOps 脚本、监控面板或者只是想让命令行输出酷起来不妨试试 jink。项目还在持续迭代欢迎提 Issue 和 PR。

更多文章