雖然 Swing/JavaFX 已成主流,但 AWT 作為 Java 原生 GUI 基礎,理解其組件模型、布局管理與事件機制,有助於掌握圖形界面編程本質。本文系統梳理 AWT 核心 API,附帶完整可運行示例。
Frame 是獨立窗口,擁有標題欄、邊框、最小化/最大化/關閉按鈕。
// 方式 1:直接實例化
Frame f = new Frame("窗口標題");
// 方式 2:繼承 Frame(推薦,便於封裝邏輯)
public class MyFrame extends Frame {
public MyFrame() {
setTitle("繼承方式窗口");
setSize(400, 300);
setLocation(200, 150);
setVisible(true);
}
}
setBounds(x, y, width, height):一次性設置位置與大小setBackground(Color):背景色,支持 RGB 構造 new Color(r, g, b)setResizable(false):禁止用戶調整大小setVisible(true):顯示窗口(默認隱藏)pack():根據子組件優先尺寸自動調整窗口大小,調用後 setSize 失效Panel 是無標題欄的輕量級容器,默認 FlowLayout,常用於組件分組佈局。
Panel p = new Panel(new FlowLayout(FlowLayout.LEFT));
p.setBounds(50, 50, 200, 100); // 相對父容器(Frame)座標
p.setBackground(new Color(200, 200, 255));
frame.add(p);
| 布局 | 默認容器 | 特點 | 構造參數 |
|---|---|---|---|
| FlowLayout | Panel | 左到右、上到下流式排列 | 對齊方式(LEFT/CENTER/RIGHT)、水平/垂直間距 |
| BorderLayout | Frame | 五大區域:NORTH, SOUTH, EAST, WEST, CENTER | 水平/垂直間距 |
| GridLayout | Frame/Panel | 規則網格,行列固定 | rows, cols, hgap, vgap |
Button btn = new Button("提交");
// BorderLayout 容器中指定位置
frame.add(btn, BorderLayout.SOUTH); // 或 frame.add(btn, "South");
TextField tf = new TextField(20); // 列數提示寬度
tf.setEchoChar('*'); // 密碼模式
tf.addActionListener(e -> {
TextField source = (TextField) e.getSource();
System.out.println("輸入內容:" + source.getText());
source.setText(""); // 清空
});
Label lbl = new Label("用戶名:", Label.RIGHT); // 對齊方式
panel.add(lbl);
繼承 Frame/Panel 並覆寫 paint 進行自定義繪製。Graphics 視為畫筆,組件視為畫布。
@Override
public void paint(Graphics g) {
Color old = g.getColor();
g.setColor(Color.RED);
g.fillRect(50, 50, 100, 60); // 實心矩形
g.drawOval(50, 130, 80, 80); // 空心圓
g.fillOval(150, 130, 80, 80); // 實心圓
g.setColor(old); // 恢復畫筆顏色
}
重繪觸發:調用 repaint() → 系統調用 update() → 清屏並調用 paint()。雙緩衝可消除閃爍。
// 獨立監聽器類
class BtnMonitor implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand(); // 獲取 setActionCommand 設置的命令字符串
System.out.println("觸發命令:" + cmd);
}
}
// 綁定
btn.setActionCommand("submit_order");
btn.addActionListener(new BtnMonitor());
frame.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
Point p = new Point(e.getX(), e.getY()); // 相對組件座標
points.add(p);
frame.repaint(); // 觸發重繪
}
});
// 匿名內部類寫法(推薦)
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0); // 正確退出 JVM
}
});
frame.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
System.out.println("↑ 被按下");
}
}
});
// 注意:組件必須可聚焦且已獲取焦點才能接收鍵盤事件
frame.setFocusable(true);
frame.requestFocus();
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
public class DrawBoard extends Frame {
private List<Point> points = new ArrayList<>();
public DrawBoard() {
setTitle("簡易繪圖板");
setBounds(100, 100, 600, 400);
setBackground(Color.WHITE);
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
points.add(e.getPoint());
repaint();
}
});
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) { System.exit(0); }
});
setVisible(true);
}
@Override
public void paint(Graphics g) {
g.setColor(Color.BLUE);
for (Point p : points) {
g.fillOval(p.x - 3, p.y - 3, 6, 6); // 畫小圓點
}
}
public static void main(String[] args) {
new DrawBoard();
}
}
setBounds、鼠標座標均相對直接父容器左上角 (0,0)。setLayout(null) 後方可使用 setBounds 絕對定位。update(Graphics g) 實現離屏繪圖。dispose() 釋放原生資源。AWT 雖輕量,但其事件委派模型、布局管理哲學、繪圖管線構成了 Java GUI 編程的基石。掌握它,遷移至 Swing/JavaFX 將毫無障礙。