1. 介绍

Lanterna 是一个用于构建文本用户界面的 Java 库,功能类似于 C 语言的 Curses 库。但 Lanterna 完全由纯 Java 编写,甚至能在纯图形环境中通过模拟终端生成终端 UI。

本文将带你快速了解 Lanterna 的核心功能和使用方法,包括:

  • 终端基础操作
  • 缓冲屏幕 API
  • 文本 GUI 组件

2. 依赖配置

使用前需添加最新版依赖(当前版本 3.1.2)。Maven 配置如下:

<dependency>
    <groupId>com.googlecode.lanterna</groupId>
    <artifactId>lanterna</artifactId>
    <version>3.1.2</version>
</dependency>

3. 终端访问

3.1 创建终端实例

推荐使用 DefaultTerminalFactory 自动适配环境:

try (Terminal terminal = new DefaultTerminalFactory().createTerminal()) {
    // 终端操作代码
}

✅ 自动选择系统终端或 Swing/AWT 模拟终端
❌ 直接实例化特定终端可能不兼容(如 SwingTerminalFrame 需图形环境)

3.2 私有模式控制

terminal.enterPrivateMode(); // 清屏并保存原始状态
// 终端操作代码
terminal.exitPrivateMode();  // 恢复原始状态

⚠️ 注意:重复进入/退出会抛异常,但 close() 方法会自动处理状态

4. 底层终端操作

4.1 基础字符输出

terminal.putCharacter('H');
terminal.putCharacter('e');
terminal.putCharacter('l');
terminal.putCharacter('l');
terminal.putCharacter('o');
terminal.flush(); // 必须刷新缓冲区

low level terminal hello

4.2 光标控制

terminal.setCursorPosition(10, 10); // 移动光标到 (10,10)
terminal.putCharacter('H');
// ... 输出 "Hello"
terminal.setCursorPosition(11, 11); // 移动到 (11,11)
// ... 输出 "World"

low level terminal move cursor

获取终端尺寸:

TerminalSize size = terminal.getTerminalSize();
System.out.println("行数: " + size.getRows());
System.out.println("列数: " + size.getColumns());

4.3 文本样式

颜色设置

terminal.setForegroundColor(TextColor.ANSI.RED); // 前景色
terminal.putCharacter('H'); // ... 输出红色 "Hello"
terminal.setForegroundColor(TextColor.ANSI.DEFAULT);
terminal.setBackgroundColor(TextColor.ANSI.BLUE); // 背景色
terminal.putCharacter('W'); // ... 输出蓝色背景 "World"

low level terminal colors

特殊样式

terminal.enableSGR(SGR.BOLD); // 启用粗体
terminal.putCharacter('H'); // ... 输出粗体 "Hello"
terminal.disableSGR(SGR.BOLD);
terminal.enableSGR(SGR.UNDERLINE); // 启用下划线
terminal.putCharacter('W'); // ... 输出下划线 "World"

low level terminal sgr

重置样式:

terminal.resetColorAndSGR(); // 恢复默认样式

4.4 键盘输入处理

while (true) {
    KeyStroke keystroke = terminal.readInput(); // 阻塞读取
    if (keystroke.getKeyType() == KeyType.Escape) {
        break; // ESC 键退出
    } else if (keystroke.getKeyType() == KeyType.Character) {
        terminal.putCharacter(keystroke.getCharacter()); // 回显字符
        terminal.flush();
    }
}

检测修饰键:

if (keystroke.isCtrlDown()) { /* Ctrl 被按下 */ }
if (keystroke.isAltDown()) {  /* Alt 被按下 */ }

5. 缓冲屏幕 API

5.1 创建屏幕实例

// 方式1:基于现有终端
try (Screen screen = new TerminalScreen(terminal)) {
    screen.startScreen();
    // 屏幕操作代码
}

// 方式2:直接创建
try (Screen screen = new DefaultTerminalFactory().createScreen()) {
    screen.startScreen();
    // 屏幕操作代码
}

⚠️ startScreen() 会自动进入私有模式,勿重复调用

5.2 屏幕绘制

单字符绘制

screen.setCharacter(5, 5,
  new TextCharacter('!',
    TextColor.ANSI.RED, TextColor.ANSI.YELLOW_BRIGHT,
    SGR.UNDERLINE, SGR.BOLD));
screen.refresh(); // 刷新屏幕

screen character

文本绘制

TextGraphics text = screen.newTextGraphics();
text.setForegroundColor(TextColor.ANSI.RED);
text.setBackgroundColor(TextColor.ANSI.YELLOW_BRIGHT);
text.putString(5, 5, "Hello");
text.putString(6, 6, "World!");
screen.refresh();

screen strings

5.3 屏幕尺寸处理

TerminalSize newSize = screen.doResizeIfNecessary();
if (newSize != null) {
    // 处理窗口大小变化
}

6. 文本 GUI 系统

6.1 GUI 初始化

MultiWindowTextGUI gui = new MultiWindowTextGUI(screen);
// 构建 GUI 组件
gui.updateScreen(); // 渲染界面

6.2 窗口管理

消息对话框

MessageDialog window = new MessageDialogBuilder()
  .setTitle("消息对话框")
  .setText("对话框内容")
  .build();
gui.addWindow(window);

gui message dialog

基础窗口

BasicWindow window = new BasicWindow("基础窗口");
window.setHints(Set.of(
    Window.Hint.CENTERED,           // 居中
    Window.Hint.NO_POST_RENDERING, // 禁用阴影
    Window.Hint.EXPANDED           // 扩展填充
));
gui.addWindow(window);

gui basic window

6.3 组件布局

单组件窗口

window.setComponent(new Label("这是一个标签"));

gui label

复杂布局

// 水平面板
Panel innerPanel = new Panel(new LinearLayout(Direction.HORIZONTAL));
innerPanel.addComponent(new Label("左"));
innerPanel.addComponent(new Label("中"));
innerPanel.addComponent(new Label("右"));

// 垂直面板
Panel outerPanel = new Panel(new LinearLayout(Direction.VERTICAL));
outerPanel.addComponent(new Label("上"));
outerPanel.addComponent(innerPanel);
outerPanel.addComponent(new Label("下"));

window.setComponent(outerPanel);

gui layouts

6.4 交互组件

TextBox textbox = new TextBox();
Button button = new Button("确定");
button.addListener((b) -> {
    System.out.println(textbox.getText()); // 获取输入
    window.close(); // 关闭窗口
});

Panel panel = new Panel(new LinearLayout(Direction.VERTICAL));
panel.addComponent(textbox);
panel.addComponent(button);
window.setComponent(panel);
gui.addWindowAndWait(window); // 阻塞等待窗口关闭

gui interactive

7. 总结

Lanterna 提供了三层 API:

  1. 底层终端操作:精确控制字符/光标/样式
  2. 缓冲屏幕 API:高效批量渲染
  3. 文本 GUI 系统:快速构建交互界面

适合场景:

  • 命令行工具增强
  • 终端游戏开发
  • 无图形环境下的交互应用

所有示例代码可在 GitHub 获取。下次需要构建文本 UI 时,不妨试试这个简单粗暴的解决方案!


原始标题:Introduction to Lanterna | Baeldung