首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Swing 事件註冊機制深度解析:匿名類、獨立監聽器與統一事件處理

     編輯:Java 相關知識

事件註冊三種寫法對比

1. 匿名內部類(最常見,適合簡單邏輯)

button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // 處理邏輯
    }
});
  • 優點:就地定義,封裝性好,無需額外類檔。
  • 缺點:邏輯複雜時程式碼膨脹;多個元件共用同邏輯需重複編寫。

2. 獨立監聽器類(適合邏輯復用、複雜業務)

// 獨立類
class ClearButtonListener implements ActionListener {
    private JTextField operand1, operand2, result;
    public ClearButtonListener(JTextField o1, JTextField o2, JTextField r) {
        this.operand1 = o1; this.operand2 = o2; this.result = r;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        operand1.setText("");
        operand2.setText("");
        result.setText("");
    }
}

// 註冊
clear.addActionListener(new ClearButtonListener(operand1, operand2, result));
  • 優點:邏輯集中,可構造函數注入依賴,便於單元測試。
  • 缺點:增加類檔數量;需手動傳遞 UI 元件引用。

3. 統一事件處理:元件實作 ActionListener(適合簡單表單)

public class Calculator extends JFrame implements ActionListener {
    private JComboBox<Integer> operatorBox;
    private JTextField operand1, operand2, result;
    private JButton btnCalc, btnClear;

    public Calculator() {
        // ... 初始化元件 ...
        btnCalc.addActionListener(this);
        btnClear.addActionListener(this);
        operatorBox.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object src = e.getSource();
        if (src == operatorBox) {
            // 切換運算符顯示
        } else if (src == btnCalc) {
            // 計算邏輯
        } else if (src == btnClear) {
            // 清空邏輯
        }
    }
}
  • 優點:所有事件集中在一處,維護方便。
  • 缺點:類職責過重;actionPerformed 易膨脹為巨大 switch/if-else。

實戰範例:簡易計算機

完整程式碼展示匿名類註冊下拉選單(切換 +/−)、計算按鈕、清除按鈕:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ComboBoxTest extends JFrame {
    private JComboBox<Integer> operatorBox = new JComboBox<>(new Integer[]{0, 1});
    private JTextField operand1 = new JTextField(10);
    private JLabel operatorLabel = new JLabel("+");
    private JTextField operand2 = new JTextField(10);
    private JTextField result = new JTextField(4);
    private JButton btnCalc = new JButton("Done");
    private JButton btnClear = new JButton("Clear");

    public ComboBoxTest() {
        // 下拉選單事件:切換運算符顯示
        operatorBox.addActionListener(e -> {
            operatorLabel.setText(operatorBox.getSelectedIndex() == 0 ? " + " : " - ");
        });

        // 計算按鈕事件
        btnCalc.addActionListener(e -> {
            try {
                int a = Integer.parseInt(operand1.getText());
                int b = Integer.parseInt(operand2.getText());
                int res = (operatorBox.getSelectedIndex() == 0) ? a + b : a - b;
                result.setText("= " + res);
            } catch (NumberFormatException ex) {
                result.setText("輸入錯誤");
            }
        });

        // 清除按鈕事件
        btnClear.addActionListener(e -> {
            operand1.setText("");
            operand2.setText("");
            result.setText("");
        });

        setLayout(new FlowLayout());
        add(new JLabel("選擇運算: 0(+) 1(-)"));
        add(operatorBox);
        add(operand1);
        add(operatorLabel);
        add(operand2);
        add(result);
        add(btnCalc);
        add(btnClear);
        setSize(350, 140);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ComboBoxTest::new);
    }
}

選型建議

場景推薦寫法
單一元件、簡單邏輯匿名類 / Lambda (Java 8+)
多元件共用相同邏輯獨立監聽器類
表單類視窗、事件數量少統一實作 ActionListener
複雜業務、需單元測試獨立類 + 依賴注入

常見錯誤避坑

  • BufferedReader readLine() 重複呼叫:while 條件與迴圈體各呼叫一次會導致跳行,正確寫法:String line; while ((line = br.readLine()) != null) { ... }
  • 事件源判斷用 == 而非 equals:e.getSource() == btn 正確,因為比較的是同一物件引用。
  • Swing 操作必須在 EDT:使用 SwingUtilities.invokeLater() 啟動 GUI。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved