第1章:SWT 是什么?

第1章:SWT 是什么?


作者:步子哥 (steper@foxmail.com)


1.1 三个比喻看懂 SWT

比喻一:翻译官与当地工匠

想象你是一个跨国公司的项目经理,
你只会说英语(Java),
但你的客户来自不同的国家:
- 美国客户说 Windows 话
- 德国客户说 Linux 话  
- 日本客户说 Mac 话

现在你要为客户建造一栋房子(GUI 应用)。

Swing 的做法:
你自己画图纸,自己选材料,
虽然你用的是英文描述,
但画出来的门窗都是你"想象中的标准门窗"
到了美国,客户说:"这不是我们美国的门窗"
到了德国,客户说:"这不是我们德国的门窗"

SWT 的做法:
你聘请了一位翻译官(SWT 库),
你用英文(Java)告诉翻译官:"我要一个按钮"
翻译官转头对当地的工匠说:
- 在美国:"Make me a Win32 button"
- 在德国:"Make me a GTK button"  
- 在日本:"Make me a Cocoa button"

工匠用他们最熟悉的材料和方法做出来,
客户一看:"这就是我们当地的按钮!"

关键点:

  • 你(Java 开发者)不需要学习当地语言(Windows API、GTK API、Cocoa API)
  • 翻译官(SWT)负责语言转换
  • 当地工匠(操作系统)负责实际建造
  • 最终呈现的是最地道的本地风格

比喻二:桥梁的两端

SWT 就像一座连接两端的桥梁:

     ┌─────────────┐
     │  Java 世界  │
     └──────┬──────┘
            │  SWT (桥梁)
     ┌──────▼──────┐
     │ 操作系统世界 │
     └─────────────┘

Java 世界这一端:
- 语言统一:都是 Java
- 逻辑清晰:面向对象编程
- 跨平台:一份代码,多处运行

操作系统世界这一端:
- 风格各异:每个系统都有原生控件
- API 不同:Windows API、GTK API、Cocoa API
- 行为一致:用户期望与系统其他应用一致

桥梁(SWT)的作用:
- 提供 Java 语言的接口(让你用 Java 调用)
- 连接不同平台的原生实现(一次编码,自动适配)
- 保持轻量:桥面不宽,够用就行

为什么需要这座桥?

没有桥的情况:
- 你要跳河游过去(学习每个系统的 API)
- 每次都要重新造桥(每次写应用都要处理跨平台问题)

有了 SWT 这座桥:
- 轻松走过去(用熟悉的 Java)
- 桥已经建好了(SWT 团队维护)
- 多次往返都方便(多个项目共用)

比喻三:操作系统 API 的披萨外卖

把操作系统 API 想象成一家披萨店:

Windows 披萨店:
- 披萨(控件)用 Windows 风格的原料
- 点餐方式:用 Windows API 语言
- 送餐员:Windows 原生控件

Linux 披萨店:
- 披萨(控件)用 GTK 风格的原料
- 点餐方式:用 GTK API 语言
- 送餐员:GTK 原生控件

Mac 披萨店:
- 披萨(控件)用 Cocoa 风格的原料
- 点餐方式:用 Cocoa API 语言
- 送餐员:Cocoa 原生控件

现在你要吃披萨(开发 GUI 应用),但你只会说 Java。

SWT 的做法:
你用 Java 下单:"我要一个按钮"
SWT 外卖员接到订单后:
- 在 Windows:给 Windows 披萨店打电话(Win32 API)
- 在 Linux:给 Linux 披萨店打电话(GTK API)
- 在 Mac:给 Mac 披萨店打电话(Cocoa API)

披萨店用他们自己的方式做披萨,
SWT 外卖员把披萨送到你面前,
你吃到的就是最地道的当地风味!

类比的边界:

  • ✅ 准确:API 调用确实像点餐,操作系统像餐馆
  • ⚠️ 边界:SWT 不是"外卖员",更像"代理",你直接通过它访问原生控件,中间没有延迟

1.2 SWT 的前世今生

从 AWT 到 Swing 再到 SWT

GUI 库的进化史,就像技术的三次浪潮:

第一次浪潮:AWT(Abstract Window Toolkit)
时间:1995 年,Java 诞生之初
特点:用最笨的方式实现跨平台
方式:用"最小公约数"策略
      - Windows 有按钮,Linux 有按钮,Mac 有按钮
      - 找它们的共同点:"都叫按钮"
      - 用最简单的按钮实现
问题:丑!太丑了!
      - 看起来像 90 年代的 Windows 3.1
      - 不同系统下外观不一致
      - 功能有限,很多系统特性用不了

第二次浪潮:Swing
时间:1998 年,Java 2 发布
特点:完全自绘,不用系统的任何控件
方式:
      - "我自己画按钮,不用你的!"
      - 所有的控件都是 Java 画的
      - 看起来一样(都丑一样,都美一样)
优点:跨平台完全一致,功能强大
问题:
      - 感觉"不像"本地应用
      - 性能不如原生
      - 用户的肌肉记忆失效
        (Mac 用户习惯了 Mac 的菜单栏,但 Swing 的菜单不一样)

第三次浪潮:SWT(Standard Widget Toolkit)
时间:2001 年,Eclipse 项目诞生
特点:拥抱原生,轻量封装
方式:
      - "用系统最好的控件,用 Java 调用"
      - 通过 JNI(Java Native Interface)连接
      - 每个平台用对应的原生库
优点:
      - 原生外观和手感
      - 性能接近原生
      - 用户感觉像本地应用
问题:
      - 不同平台行为有差异(但这是特性,不是 bug)
      - 需要分发平台相关的库

Eclipse 的诞生故事

2001 年,IBM 投入 4000 万美元,启动了一个秘密项目:
目标:打造一个统一的开发工具平台,取代 VisualAge

项目代号:Eclipse(日食,意为"遮蔽一切")

技术挑战:
- 当时 IBM 用的是 VisualAge for Java,基于 Swing
- Swing 的性能和外观都不够理想
- 用户体验不如 Visual Studio(Windows 原生)

关键决策:
IBM 决定:不用 Swing,自己做一个 GUI 库

为什么不用 Swing?
- Swing 太慢
- Swing 不像 Windows 应用(Visual Studio 对手)
- Swing 难以定制(IBM 需要深度定制)

SWT 的诞生:
- IBM 用 C++ 写了 Windows 原生库(.dll)
- 用 Java 写了统一的 API
- 通过 JNI 连接两者
- 后来又支持了 Linux(GTK)和 Mac(Cocoa)

开源的决定:
2004 年,IBM 将 Eclipse 捐赠给 Eclipse 基金会
从此,Eclipse 和 SWT 成为开源世界的瑰宝

费曼问题:为什么叫 Standard Widget Toolkit?

"Standard" 的含义:
- 不是"统一标准"(像 Swing 那样每个平台一样)
- 而是"使用平台的标准控件"
- Windows 用 Windows 标准,Linux 用 Linux 标准

"Widget Toolkit" 的含义:
- Widget 就是控件(按钮、文本框等)
- Toolkit 是工具包
- 合起来就是:操作标准控件的工具包

1.3 SWT vs Swing vs JavaFX

一张表看清三者的差异

特性AWTSwingJavaFXSWT
原生控件✅ 部分使用❌ 全部自绘❌ 全部自绘✅ 完全使用
外观丑陋可自定义但非原生现代化但非原生原生
性能一般较好
跨平台一致性差(功能受限)好(完全一致)好(完全一致)差(行为有差异)
学习曲线简单中等中等简单
打包部署简单简单复杂(需要 JavaFX 模块)需要分发原生库
社区活跃度停止维护维护中维护中活跃(Eclipse 生态)
适合场景已淘汰内部工具现代化应用桌面应用、IDE

何时选择 SWT?

选择 SWT 的场景:

  1. 需要原生外观和手感

`` 例如: - Windows 用户希望应用看起来像 Windows 应用 - Mac 用户希望应用遵循 Mac 的设计规范 - Linux 用户希望应用与 GNOME/KDE 融为一体 ``

  1. 性能要求高

`` 例如: - 需要频繁更新大量控件(如表格、树) - 需要流畅的动画效果 - 需要处理大量数据 ``

  1. 已有 Eclipse 插件生态

`` 例如: - 开发 Eclipse 插件 - 使用基于 SWT 的框架(如 RCP) ``

  1. 用户熟悉原生交互

`` 例如: - 企业内部应用,用户习惯了本地应用 - 工具软件,需要快捷键、菜单等原生特性 ``

不选择 SWT 的场景:

  1. 需要完全一致的跨平台外观

`` 例如: - 品牌要求所有平台完全一致 - 需要高度定制的 UI ``

  1. 需要现代化 UI 特性

`` 例如: - 需要 CSS 样式支持 - 需要 3D 图形支持(JavaFX 更好) - 需要动画和过渡效果(JavaFX 更丰富) ``

  1. 不想分发原生库

`` 例如: - 简单的内部工具 - 快速原型开发 ``


1.4 SWT 的设计哲学

"原生优先":让应用像本地应用

SWT 的核心信念:
用户不应该知道你的应用是用 Java 写的。

用户的感觉应该是:
- "这是一个 Windows 应用"
- "这是一个 Mac 应用"  
- "这是一个 Linux 应用"

如何实现?
- 使用操作系统的原生按钮、菜单、对话框
- 遵循操作系统的设计规范
  - Mac:菜单栏在屏幕顶部
  - Windows:菜单栏在窗口顶部
- 支持系统的快捷键
  - Mac:Cmd+C 复制
  - Windows/Linux:Ctrl+C 复制
- 支持系统主题
  - Windows 遵循系统颜色
  - Linux 遵循 GTK 主题
  - Mac 遵循系统外观

费曼测试:

问一个 Mac 用户:"你觉得这个应用是用什么写的?"
如果他回答:"不知道,但感觉像 Mac 应用"
这就是 SWT 的成功。

如果他回答:"感觉不像 Mac 应用"
那就说明出了问题。

"薄薄一层":不重复造轮子

SWT 的设计理念:
只做必要的事情,不做多余的事情。

薄薄一层的含义:
- Java API → JNI → 原生库
- 中间没有臃肿的抽象层
- 直接调用系统 API,几乎零开销

对比 Swing(厚厚一层):
Java API ──→ Swing 实现 ──→ Java 2D ──→ 操作系统绘图 API
           (自绘按钮)      (自己画像素)
           
问题:
- 每次点击按钮,Swing 都要画像素
- 不是调用系统按钮,而是"假装"按钮
- 性能开销大

SWT(薄薄一层):
Java API ──→ JNI ──→ 系统按钮 API
                    (真正调用按钮)
                    
优势:
- 点击按钮直接调用系统 API
- 系统按钮已经优化,性能好
- 代码量少,维护成本低

类比的边界:

  • ✅ 准确:SWT 确实比 Swing 薄,因为不重复造轮子
  • ⚠️ 边界:"薄"不等于"简单",适配多个平台本身就很复杂,但对使用者来说是"薄"的

"掌控与放手":在 Java 与系统之间平衡

SWT 的平衡术:
- 掌控:让开发者用 Java 控制一切
- 放手:让系统自己处理细节

掌控部分(Java API):
- 用面向对象的方式创建控件
- 用监听器处理事件
- 用布局管理器管理布局
- 用统一的 API 跨平台调用

放手部分(系统处理):
- 按钮的外观由系统决定
- 菜单的行为由系统决定
- 滚动条的表现由系统决定
- 快捷键由系统处理

例子:按钮的悬停效果
// 你只需要创建按钮,告诉它要做什么
Button button = new Button(shell, SWT.PUSH);
button.setText("点击我");
button.addListener(SWT.Selection, event -> {
    // 处理点击事件
});

// 悬停效果(鼠标移上去变亮)由系统自动处理
// 你不需要写任何代码

如果用 Swing(需要掌控一切):

// 你需要自己处理悬停效果
button.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseEntered(MouseEvent e) {
        button.setBackground(Color.LIGHT_GRAY);
    }
    
    @Override
    public void mouseExited(MouseEvent e) {
        button.setBackground(null);
    }
});

SWT 的哲学:

能放手就放手,让系统做它擅长的事情
该掌控就掌控,让开发者控制应用逻辑

1.5 本章小结

三个比喻回顾

比喻核心思想伏笔(后续会展开)
翻译官SWT 让你用 Java 调用原生控件第 2 章会详细讲解 JNI 原理
桥梁SWT 连接 Java 世界和操作系统世界第 13 章会讲解系统级集成
披萨外卖SWT 封装了原生 API 的复杂性第 11 章会讲解资源管理

关键要点

  1. SWT 是什么?

- Standard Widget Toolkit(标准控件工具包) - 通过 JNI 调用操作系统原生控件 - 轻量级的 Java GUI 库

  1. 为什么选择 SWT?

- 原生外观和手感 - 性能好 - 适合桌面应用开发

  1. SWT 的设计哲学?

- 原生优先 - 薄薄一层 - 掌控与放手

下一章预告

现在你已经理解了 SWT 的本质,
下一章,我们将动手搭建环境,
写出你的第一个 SWT 程序。

就像学会了语言理论,
现在要开始实际对话了。

练习题:

  1. 用自己的话解释 SWT 和 Swing 的区别?
  2. 如果你是一个 Windows 用户,你会更倾向于使用 SWT 还是 Swing?为什么?
  3. SWT 的"薄薄一层"是什么意思?为什么这样设计?

(答案在本章中,自己找找看)

← 返回目录