Java 桌面程序开发全攻略
Java 不仅仅是为服务器端和安卓应用而生,它同样拥有强大而成熟的桌面应用开发生态,无论是构建简单的工具软件,还是复杂的跨平台客户端,Java 都能胜任。

本教程将分为以下几个部分:
- 入门基础:Swing
- 现代选择:JavaFX
- 高级主题:打包、数据库、多线程
- 推荐学习资源
第一部分:入门基础 - Swing (Java Foundation Classes - JFC)
Swing 是 Java 最早、也是最经典的 GUI 工具包,它使用纯 Java 编写,不依赖于本地平台,因此具有“一次编写,到处运行”的跨平台特性,虽然其外观可能略显传统,但它是理解 GUI 编程核心概念的最佳起点。
核心概念
- 组件: GUI 界面上的基本元素,如按钮、标签、文本框等,所有组件都继承自
JComponent类。 - 容器: 用于存放其他组件的特殊组件,常见的容器有
JFrame(主窗口)、JPanel(面板)。 - 布局管理器: 负责决定容器中组件的位置和大小,常见的有
FlowLayout(流式布局)、BorderLayout(边界布局)、GridLayout(网格布局) 和GridBagLayout(网格包布局,最灵活也最复杂)。 - 事件处理: GUI 程序的核心,用户与组件交互(如点击按钮、输入文本)会触发事件,通过“监听器”来响应这些事件。
第一个 Swing 程序:Hello World
让我们创建一个最简单的窗口,上面带一个按钮。
步骤 1:创建主窗口

JFrame 是所有 Swing GUI 程序的顶层容器。
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class FirstSwingApp {
public static void main(String[] args) {
// 使用 SwingUtilities.invokeLater 确保 GUI 创建在事件分发线程上
SwingUtilities.invokeLater(() -> {
// 1. 创建主窗口
JFrame frame = new JFrame("我的第一个 Swing 窗口");
// 2. 设置窗口大小 (宽 x 高)
frame.setSize(400, 300);
// 3. 设置窗口关闭时的默认操作 (EXIT_ON_CLOSE 表示退出程序)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 4. 设置窗口居中显示
frame.setLocationRelativeTo(null);
// 5. 显示窗口
frame.setVisible(true);
});
}
}
运行结果:你会看到一个标题为“我的第一个 Swing 窗口”的空白窗口。
代码解析:
SwingUtilities.invokeLater(...)是一个非常重要的方法,它确保所有与 GUI 相关的代码都在“事件分发线程”(EDT)上执行,这是线程安全的最佳实践。JFrame创建了窗口框架,但需要setVisible(true)才能显示出来。
步骤 2:添加组件

现在我们在窗口里添加一个按钮和一个标签。
import javax.swing.*;
import java.awt.*;
public class SimpleApp {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("简单应用");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 200);
frame.setLocationRelativeTo(null);
// 1. 创建一个面板作为容器,并设置布局
JPanel panel = new JPanel();
// 使用 FlowLayout,组件会像文本一样从左到右排列
panel.setLayout(new FlowLayout());
// 2. 创建组件
JLabel label = new JLabel("你好, Swing!");
JButton button = new JButton("点击我");
// 3. 将组件添加到面板中
panel.add(label);
panel.add(button);
// 4. 将面板添加到窗口的内容面板中
frame.getContentPane().add(panel);
frame.setVisible(true);
});
}
}
运行结果:窗口中会显示一个标签和一个按钮。
代码解析:
- 我们通常不直接把组件加到
JFrame,而是加到JFrame的“内容面板”(ContentPane)上。getContentPane()方法可以获取这个面板。 JPanel是一个通用的轻量级容器,我们用它来组织其他组件,并设置布局管理器。
步骤 3:处理事件
让按钮点击后,改变标签的文字。
// ... (前面的代码相同) ...
// 在 main 方法内部,创建组件后
JLabel label = new JLabel("你好, Swing!");
JButton button = new JButton("点击我");
// 1. 为按钮添加动作监听器
button.addActionListener(e -> {
// 当按钮被点击时,这段代码会执行
label.setText("按钮被点击了!");
});
// ... (将组件添加到面板) ...
运行结果:点击按钮,标签的文字会立即改变。
代码解析:
addActionListener(...)方法为按钮注册了一个“动作监听器”。- 我们使用了 Java 8 的 Lambda 表达式
e -> {...}来简化匿名内部类的写法。e是ActionEvent对象,包含了事件的相关信息。
常用 Swing 组件一览
| 组件名称 | 类名 | 用途 |
|---|---|---|
| 按钮 | JButton |
触发一个动作 |
JLabel |
显示文本或图标 | |
| 文本框 | JTextField |
单行文本输入 |
| 密码框 | JPasswordField |
单行密码输入,显示为掩码 |
| 文本区域 | JTextArea |
多行文本输入/显示 |
| 复选框 | JCheckBox |
选择一个或多个选项 |
| 单选框 | JRadioButton |
在一组选项中只选一个 |
| 下拉框 | JComboBox |
提供一个下拉列表供用户选择 |
| 列表框 | JList |
显示一个可滚动的项目列表 |
| 表格 | JTable |
以表格形式显示数据 |
| 树 | JTree |
以分层结构显示数据 |
第二部分:现代选择 - JavaFX
Swing 虽然经典,但已经显得有些陈旧,JavaFX 是 Oracle 官方推出的新一代 GUI 工具包,它拥有更现代的视觉效果、更强大的 UI 控件(如 WebView 内嵌浏览器、Chart 图表)以及基于 CSS 的样式化能力。
重要提示:从 Java 11 开始,JavaFX 已经不再包含在 JDK 中,需要单独下载。
JavaFX 与 Swing 的核心区别
- 架构:Swing 是 AWT 的轻量级版本,依赖重量级容器,JavaFX 是一个全新的、完全基于图形硬件加速的框架。
- 语言:Swing 使用 Java 代码来构建 UI,JavaFX 推荐使用 FXML (一种基于 XML 的标记语言) 来描述 UI,将 UI 逻辑与业务逻辑分离,类似于网页开发中的 HTML 和 JavaScript。
- 样式:Swing 的样式定制能力有限,JavaFX 支持使用 CSS 来美化界面,非常灵活。
- 功能:JavaFX 提供了内置的图表、动画、媒体播放等高级功能,而 Swing 通常需要第三方库。
第一个 JavaFX 程序:Hello World
步骤 1:设置项目环境
如果你使用 Maven,在 pom.xml 中添加 JavaFX 依赖:
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>21</version> <!-- 使用你想要的版本 -->
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>21</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<executions>
<execution>
<!-- Default configuration for running with: mvn javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>com.example.MainApp</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
步骤 2:编写主程序
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HelloJavaFX extends Application {
@Override
public void start(Stage primaryStage) {
// 1. 创建一个按钮
Button btn = new Button();
btn.setText("点击我");
// 2. 为按钮添加事件处理器
btn.setOnAction(event -> {
System.out.println("Hello World!");
btn.setText("你好, JavaFX!");
});
// 3. 创建一个布局容器,并将按钮放入其中
StackPane root = new StackPane();
root.getChildren().add(btn);
// 4. 创建一个场景,并将布局放入场景中
Scene scene = new Scene(root, 300, 250);
// 5. 将场景设置到舞台(窗口)上
primaryStage.setTitle("Hello JavaFX");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
// 启动 JavaFX 应用程序
launch(args);
}
}
运行结果:与 Swing 版本的 Hello World 类似,点击按钮后控制台打印信息,按钮文字改变。
JavaFXML 示例(推荐方式)
这是 JavaFX 的标准开发模式。
步骤 1:创建 FXML 文件 (hello-view.fxml)
在 src/main/resources 目录下创建 hello-view.fxml 文件。
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox alignment="CENTER" spacing="20.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.HelloController">
<children>
<Label text="欢迎使用 JavaFXML!" />
<Button text="点击我" onAction="#handleButtonClick" />
</children>
</VBox>
VBox: 垂直布局的容器。fx:controller: 指定与此 UI 关联的控制器类。onAction="#handleButtonClick": 指定按钮点击时调用的控制器方法名。
步骤 2:创建控制器类 (HelloController.java)
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
public class HelloController {
@FXML
private Label welcomeText; // FXML 中的组件需要用 @FXML 注解
@FXML
private Button helloButton;
@FXML
protected void onHelloButtonClick() {
welcomeText.setText("欢迎来到 JavaFXML 世界!");
}
// 或者使用 FXML 中指定的方法名
@FXML
protected void handleButtonClick() {
welcomeText.setText("按钮被点击了!");
}
}
@FXML: 注解告诉 FXML 加载器,这个字段或方法需要从 FXML 文件中注入。- 方法名必须与 FXML 文件中
onAction属性指定的值匹配(去掉 )。
步骤 3:修改主程序以加载 FXML
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class MainApp extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
stage.setTitle("JavaFXML 应用");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
第三部分:高级主题
打包你的应用
- Swing: 可以使用
Maven Assembly Plugin或Maven Shade Plugin将所有依赖打包成一个可执行的 JAR 文件。 - JavaFX: 强烈推荐使用
jpackage工具,它可以直接将你的 JavaFX 应用打包成原生安装包(如.exe,.msi,.dmg,.deb),用户无需安装 Java 运行环境即可运行。
使用 jpackage 打包示例:
# 假设你的主类是 com.example.MainApp # 并且你有一个名为 "HelloJavaFX" 的模块 (在 module-info.java 中定义) jpackage --type exe --name MyJavaFXApp --input target/libs --main-jar MyJavaFXApp.jar --main-class com.example.MainApp --module-path "C:/path/to/javafx-sdk-21/lib" --add-modules javafx.controls,javafx.fxml
连接数据库
桌面应用通常需要持久化数据,最常用的方式是连接关系型数据库。
技术栈:
- 数据库: SQLite (轻量级,无需安装服务器), MySQL, PostgreSQL 等。
- JDBC 驱动: 每种数据库都有其对应的 JDBC 驱动。
- 连接池: 如 HikariCP,用于高效管理数据库连接。
示例代码 (使用 SQLite 和 JDBC):
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DatabaseExample {
private static final String DB_URL = "jdbc:sqlite:mydatabase.db";
public static void main(String[] args) {
// 1. 加载驱动 (对于 JDBC 4.0+,通常可以省略)
try {
Class.forName("org.sqlite.JDBC");
} catch (ClassNotFoundException e) {
e.printStackTrace();
return;
}
// 2. 建立连接
try (Connection conn = DriverManager.getConnection(DB_URL)) {
if (conn != null) {
System.out.println("已成功连接到数据库。");
// 3. 创建表 (如果不存在)
String sql = "CREATE TABLE IF NOT EXISTS users (\n" +
" id integer PRIMARY KEY,\n" +
" name text NOT NULL,\n" +
" email text NOT NULL UNIQUE\n" +
");";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.execute();
}
// 4. 插入数据
sql = "INSERT INTO users(name, email) VALUES(?,?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "张三");
pstmt.setString(2, "zhangsan@example.com");
pstmt.executeUpdate();
}
// 5. 查询数据
sql = "SELECT id, name, email FROM users";
try (PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getInt("id") + "\t" +
rs.getString("name") + "\t" +
rs.getString("email"));
}
}
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}
多线程与 GUI
绝对禁止在事件分发线程上执行耗时操作!(如网络请求、文件 I/O、复杂计算),否则会导致整个 GUI 界面“卡死”(无响应)。
正确做法:使用 SwingWorker (Swing) 或 Task (JavaFX)。
JavaFX Task 示例:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ThreadExample extends Application {
private Label statusLabel = new Label("准备就绪");
@Override
public void start(Stage primaryStage) {
Button startButton = new Button("开始耗时任务");
startButton.setOnAction(e -> startLongTask());
VBox root = new VBox(10, statusLabel, startButton);
Scene scene = new Scene(root, 300, 200);
primaryStage.setTitle("多线程示例");
primaryStage.setScene(scene);
primaryStage.show();
}
private void startLongTask() {
// 1. 创建一个 Task
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
// 这是后台线程,可以安全地执行耗时操作
for (int i = 1; i <= 10; i++) {
// 更新进度
updateProgress(i, 10);
// 更新消息
updateMessage("正在处理: " + i * 10 + "%");
// 模拟耗时工作
Thread.sleep(500);
}
return null;
}
};
// 2. 监听任务状态变化,更新 GUI
task.messageProperty().addListener((obs, oldVal, newVal) -> {
// 这段代码会在 EDT 上执行
statusLabel.setText(newVal);
});
// 3. 在新线程中执行任务
Thread thread = new Thread(task);
thread.setDaemon(true); // 设置为守护线程,这样当主程序结束时,它也会结束
thread.start();
}
public static void main(String[] args) {
launch(args);
}
}
第四部分:推荐学习资源
-
官方文档:
- JavaFX 文档: 最权威的参考资料。
- Swing 教程 (Oracle): 经典的 Swing 入门教程。
-
在线教程和课程:
- Udemy / Coursera: 搜索 "Java Swing", "JavaFX" 等关键词,有很多高质量的实战课程。
- Baeldung: 提供了大量关于 JavaFX 和 Swing 的简短、 focused 的文章和示例。
- YouTube: "Java GUI Tutorial", "JavaFX Tutorial" 等关键词下有大量视频教程,适合初学者。
-
社区和问答:
- Stack Overflow: 解决具体问题的最佳去处,提问时记得加上
swing,javafx,java-gui等标签。
- Stack Overflow: 解决具体问题的最佳去处,提问时记得加上
总结与建议
- 如果你是初学者,或者只需要开发一个简单的、对界面美观度要求不高的工具:从 Swing 开始是不错的选择,它能让你快速理解 GUI 编程的核心思想。
- 如果你正在开发一个新的、现代化的桌面应用,或者对 UI 效果、功能有较高要求:强烈推荐使用 JavaFX,它是 Java 桌面应用的未来,拥有更强大的功能和更优秀的开发体验。
- 无论选择哪个框架,请务必遵循 事件分发线程 的原则,并学会使用 FXML (JavaFX) 或 MVC 模式来组织你的代码,这将使你的项目更易于维护和扩展。
