Swing 雖然屬於較早期的 GUI 技術,但其輕量級、跨平台、API 穩定的特點使其仍是學習桌面開發、構建內部小工具的優秀選擇。標準開發流程包含五個關鍵步驟:
JFrame 作為頂層容器getContentPane() 承載組件
import javax.swing.*;
import java.awt.*;
public class SwingDemo1 {
public static void main(String[] args) {
// 1. 主窗體
JFrame frame = new JFrame("Swing 入門示例");
// 2. 內容面板
Container cp = frame.getContentPane();
// 3. 佈局管理器:流式佈局,左對齊,間距 20px
cp.setLayout(new FlowLayout(FlowLayout.LEFT, 20, 20));
// 4. 創建並配置組件
JLabel label1 = new JLabel("Hello World!");
JLabel label2 = new JLabel("Bye World!");
label1.setBackground(Color.BLUE);
label1.setOpaque(true); // 必須設置不透明才能顯示背景色
cp.add(label1);
cp.add(label2);
// 5. 窗體屬性配置
frame.setSize(300, 150);
frame.setLocationRelativeTo(null); // 屏幕居中
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 關閉退出程序
frame.setVisible(true);
}
}
| 佈局管理器 | 特點 | 適用場景 |
|---|---|---|
| FlowLayout | 流式左到右,換行 | 簡單工具欄、按鈕組 |
| BorderLayout | 東南西北中五區域 | 主窗體整體結構 |
| GridLayout | 規則網格 | 計算器、棋盤、表單 |
| GridBagLayout | 最靈活,組件可跨行列 | 複雜表單、儀表板 |
| BoxLayout | 單行/單列堆疊 | 工具欄、側邊欄 |
| GroupLayout | IDE 可視化設計首選 | Matisse (NetBeans) / WindowBuilder (Eclipse) |
// 匿名內部類監聽器
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按鈕被點擊!");
}
});
// Lambda 表達式 (Java 8+)
button.addActionListener(e -> System.out.println("點擊!"));
// 窗口關閉事件兩種寫法等價
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 等同於:
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
完整展示組件繼承、事件處理、狀態管理、網格佈局應用。
package com.example.swing;
import javax.swing.*;
import java.awt.*;
public class TicTacToeGame extends JFrame {
private JPanel boardPanel;
public TicTacToeGame() {
setTitle("井字遊戲");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 500);
setLocationRelativeTo(null);
boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(3, 3, 5, 5)); // 3x3 網格,間距 5px
// 創建 9 個自定義按鈕
for (int i = 0; i < 9; i++) {
boardPanel.add(new XOButton());
}
add(boardPanel);
setVisible(true);
}
public static void main(String[] args) {
// 確保在 EDT (Event Dispatch Thread) 中創建 GUI
SwingUtilities.invokeLater(TicTacToeGame::new);
}
}
class XOButton extends JButton implements ActionListener {
private Icon xIcon;
private Icon oIcon;
private int state = 0; // 0:空, 1:X, 2:O
public XOButton() {
// 從 classpath 加載圖標資源
xIcon = new ImageIcon(getClass().getResource("/images/x.png"));
oIcon = new ImageIcon(getClass().getResource("/images/o.png"));
setPreferredSize(new Dimension(150, 150));
addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
// 狀態循環:空 -> X -> O -> 空
state = (state + 1) % 3;
switch (state) {
case 0: setIcon(null); break;
case 1: setIcon(xIcon); break;
case 2: setIcon(oIcon); break;
}
// 實戰中這裡需添加:勝利判定、雙人輪流、AI 對戰邏輯
}
}
所有 GUI 創建與更新操作必須在事件分發線程 (EDT) 中執行:
SwingUtilities.invokeLater(() -> {
new MyFrame().setVisible(true);
});
// 長耗時任務使用 SwingWorker 避免凍結界面
SwingWorker<Void, Integer> worker = new SwingWorker<>() {
@Override
protected Void doInBackground() {
// 後台執行耗時操作
for (int i = 0; i <= 100; i++) {
publish(i); // 發布進度
Thread.sleep(50);
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
progressBar.setValue(chunks.get(chunks.size()-1)); // EDT 中更新 UI
}
};
worker.execute();
// 設置系統原生外觀
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
// 或使用扁平化現代風格 (需引入 FlatLaf 庫)
// UIManager.setLookAndFeel(new FlatLightLaf());
src/main/resources,通過 getClass().getResource() 加載JComponent.setUI() 共享 UI 委託對象frame.dispose() 而非僅 setVisible(false)Swing 雖非最新技術,但其設計模式豐富(組合、裝飾器、命令、觀察者)、API 成熟穩定,是理解 GUI 程式設計本質的絕佳教具。掌握 Swing 佈局管理、事件處理、線程模型,遷移至 JavaFX 或 Web 前端開發將毫無障礙。建議從簡單工具開始,逐步挑戰複雜界面,享受「所見即所得」的編程樂趣。