简体中文
GitHub
主题

Java 的桌面 UI

用 Java 写桌面应用,像素由自己绘制。

Limn 自己绘制每一个像素。组件、布局、文本、图表、媒体与 3D 视口,只需一个依赖,没有 Swing,没有 JavaFX,底下也没有原生工具包。

JDK 17 · Windows、macOS、Linux · Apache-2.0

用 Claude Code 公开地做出来:代码由 Claude 编写,由人来把握方向、做验证。造它的代价已经付过了,你不必再付一次。 Limn 是怎么做出来的

本次构建期间由 Limn 渲染的演示应用。
本次构建期间由 Limn 渲染的演示应用。
本次构建期间由 Limn 渲染的演示应用。

立刻试试

演示与主题编辑器,直接来自 Maven Central。无需克隆;没有 JDK 时 jbang 会自动获取。JBang 只解析一次最新版本并保留下来:要获取更新的版本,请加上 --fresh。

# 陈列
jbang demo@limn-toolkit/limn-toolkit
# 主题编辑器
jbang theme-editor@limn-toolkit/limn-toolkit
# 陈列
jbang --java-options=-XstartOnFirstThread demo@limn-toolkit/limn-toolkit
# 主题编辑器
jbang --java-options=-XstartOnFirstThread theme-editor@limn-toolkit/limn-toolkit

五分钟

一个依赖和一个 main 方法

没有标记语言,没有注解处理器,没有构建插件。加上后端,它会把工具包一起带来,写普通的 Java,你就有了一个窗口。

阅读安装指南
build.gradle.kts
dependencies {
    implementation("io.github.limn-toolkit:limn-backend-lwjgl:1.0.0")
}
pom.xml
<dependency>
  <groupId>io.github.limn-toolkit</groupId>
  <artifactId>limn-backend-lwjgl</artifactId>
  <version>1.0.0</version>
</dependency>
Main.java
import limn.backend.Backend;
import limn.backend.NativeWindow;
import limn.backend.WindowConfig;
import limn.backend.lwjgl.LwjglBackend;
import limn.components.Button;
import limn.components.Label;
import limn.scene.Insets;
import limn.scene.Scene;
import limn.scene.layout.Column;
import limn.scene.layout.Padding;

/** A window with a label and a button that closes it. */
public final class HelloWindow {

    public static void main(String[] args) {
        // macOS needs -XstartOnFirstThread on the JVM command line; it is macOS-only and a
        // JVM elsewhere given it will not start.
        try (Backend backend = new LwjglBackend()) {
            NativeWindow window = backend.createWindow(
                    WindowConfig.of("Hello, Limn", 480, 320));

            Column column = new Column();
            column.gap(12);
            column.add(new Label("A window, drawn by Limn."));
            column.add(new Button("Close").onAction(window::requestClose));

            Scene scene = new Scene(new Padding(Insets.all(24), column));
            scene.bind(window);

            backend.runEventLoop();
        }
    }
}

你会得到什么

一套不必自己造的组件

按钮、输入框、列表、表格、树、日期选择器、标签页、菜单、对话框、卡片、分栏、取色器,柱状图、折线图与环形图,还有一个虚拟化列表,其中一百万行的开销与二十行相同。每一个都从主题读取颜色、形状与密度,所以没有写死的值,紧凑模式只要一行。在窗口之外,应用还能打印到纸上或导出 PDF,在托盘里放一个图标,把菜单放进 macOS 的菜单栏,并与其他程序互相拖放。

查看全部
Button
Button
ComboBox
ComboBox
Slider
Slider
SegmentedControl
SegmentedControl
Checkbox and switch
Checkbox and switch
Spinner
Spinner

装得进脑子的布局

六个组件加一个标记:列纵向堆叠,行横向铺开,折行容器在宽度用尽时另起一行,网格让单元格横竖对齐,栈层层叠加,内边距向内收,Expanded 决定谁占据剩下的空间。Opacity 与 Transform 让窗口的一部分淡入淡出、移动、缩放和旋转,而不打乱周围的布局。没有约束求解器要配置,也没有布局管理器要安装。

阅读布局指南
用 Limn 排版的窗口
用 Limn 排版的窗口
一个由列、行、分栏和一个 Expanded 组成的窗口。

不需要框架的表单

字段就是组件,校验规则就是监听器,提交就是一次方法调用。没有要绑定的,也没有要注册的;用户一改正,校验状态就把字段的颜色变回去。

阅读表单指南
用 Limn 构建的表单
用 Limn 构建的表单
标签、校验、一个选择项和操作行。

表格、树与日期,已经造好

表格是架在你的应用自己持有的列表上的带类型的列,由工具包或你的服务器排序,还有一行会求和的表尾。树是架在你提供的子节点上的大纲,一行可以在说出子节点的名字之前先承诺它们存在。日期字段以读者自己的历法输入一个 ISO 日期,日期选择器则在它后面打开一个月份网格。

阅读列表指南
Limn 窗口中的表格、树和两个日期组件
Limn 窗口中的表格、树和两个日期组件
一个窗口里的表格、树、日期字段和日期选择器。

视频与 3D 同样是组件

基于物理的 3D 视口和视频播放器,像普通组件一样参与合成:滚动视图会裁剪它们,栈会画在它们上面,它们参与布局的方式与一个标签无异。

阅读媒体指南
Limn 的 3D 视口
Limn 的 3D 视口
合成进普通窗口中的 3D 视口。

为每一个人

每一种语言,每一种屏幕阅读器

用你的用户的语言

拉丁、希腊、西里尔与中日韩文字可混在同一个字符串里,字体按同一种文字的连续片段选择。阿拉伯文、希伯来文、天城文和泰文会被正确塑形——连写、合字、附加符号——从右到左的语言则让整个窗口镜像:行、边距、滚动条、方向键。输入法在字段内组字,编辑按字素移动。

阅读文本指南
同一个界面分别用日语、简体中文、韩语和俄语截取,拼接成一个窗口。
同一个界面分别用日语、简体中文、韩语和俄语截取,拼接成一个窗口。
同一个界面,在本次构建中以四种语言截取。

用同样的语言,读出来

Windows 上的屏幕阅读器、macOS 的 VoiceOver 和 Linux 的 Orca 通过各平台自己的无障碍 API 读取 Limn 窗口,你的应用无需任何平台代码。每个控件都以界面所用的语言,自己说出角色、名称和状态。为控件命名只需一次调用。

阅读无障碍指南
  1. heading“Create your account”
  2. label“Full name”
  3. text field“Full name”label · focusable, editable, required
  4. label“12 / 40”
  5. label“Email”
  6. text field“Email”label · focusable, editable, invalid, required
  7. label“Enter an address like ada@example.com”
  8. label“Password”
  9. password field“Password”label · focusable, editable, password
  10. label“At least 12 characters”
  11. label“Plan”
  12. combo box“Plan”label · focusable, expandable, has-popup
  13. switch“Email me release notes”focusable, checked
  14. separatorhorizontal
上面的表单,正如屏幕阅读器被告知的那样,在本次构建中捕获。

是你的产品气质,不是工具包的

你的应用该像你的产品,而不像它所依赖的那个库。主题就是纯数据(每一种颜色、圆角半径、每个控件继承的尺寸档位),运行时一次调用即可整套替换。品牌字体从你自己掌握的文件加载,工具包自带的观感一点都不会留下。

主题是怎么工作的
同一个控件密集的界面并排渲染七次,每一条都用不同的配色、尺寸档位和字体。

同样的组件,七种主题

把指针移到某一列上,就能看到该主题铺满整个界面。点按某一列查看该主题,左右滑动即可切换。

同一个界面,七套主题。每一条背后的代码完全相同。

公开

Limn 是怎么做出来的

Limn 的代码由 Anthropic 的模型 Claude 在 Claude Code 中编写,由人来把握方向并加以验证。我们一开始就说明这一点,因为你会想知道。

把握方向,指的是每一项设计决定都先在 docs/adr 里写成文字、经过论证并被接受,然后才有代码。加以验证,指的是每一次改动都要跑过比代码本身还庞大的测试套件;无障碍不靠假设,而是真的去听——让 Windows 上的屏幕阅读器、macOS 的 VoiceOver 和 Linux 的 Orca 朗读真实的窗口;代码也经过了多轮关于正确性、性能和 API 设计的审查。

走到这一步,用了成千上万次模型调用和数以百万计的生成 token。按 COCOMO II 估算模型,不算测试,这十余万行代码相当于一支约二十人的团队两年多的工作量。这份工作已经做完了。你可以在它之上构建,而不必重做一遍。

阅读设计记录

五分钟,让窗口出现在屏幕上

安装指南以一个能跑起来的程序收尾。此后的一切,就是指南、组件画廊和 API 参考。