本文目录导读:

我来通过一个简单的计算器案例,系统地讲解Java事件监听机制,这个案例会从最基础的版本逐步扩展到更完善的实现。
最基础版本(理解核心概念)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CalculatorV1 {
public static void main(String[] args) {
// 创建窗口
JFrame frame = new JFrame("简易计算器 V1");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建组件
JTextField num1Field = new JTextField(10);
JTextField num2Field = new JTextField(10);
JButton addButton = new JButton("相加");
JLabel resultLabel = new JLabel("结果: ");
// 设置布局
JPanel panel = new JPanel();
panel.add(new JLabel("数字1:"));
panel.add(num1Field);
panel.add(new JLabel("数字2:"));
panel.add(num2Field);
panel.add(addButton);
panel.add(resultLabel);
// 核心:注册事件监听器
// ActionListener是一个接口,我们通过匿名内部类实现它
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
// 获取输入
double num1 = Double.parseDouble(num1Field.getText());
double num2 = Double.parseDouble(num2Field.getText());
// 进行计算
double result = num1 + num2;
// 显示结果
resultLabel.setText("结果: " + result);
} catch (NumberFormatException ex) {
resultLabel.setText("输入格式错误!");
}
}
});
frame.add(panel);
frame.setVisible(true);
}
}
使用内部类实现(更好的组织代码)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CalculatorV2 {
private JFrame frame;
private JTextField num1Field;
private JTextField num2Field;
private JLabel resultLabel;
public CalculatorV2() {
initializeGUI();
addEventListeners();
}
private void initializeGUI() {
frame = new JFrame("简易计算器 V2");
frame.setSize(400, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
num1Field = new JTextField(10);
num2Field = new JTextField(10);
resultLabel = new JLabel("结果: ");
// 创建多个按钮
JButton addBtn = new JButton("+");
JButton subtractBtn = new JButton("-");
JButton multiplyBtn = new JButton("×");
JButton divideBtn = new JButton("÷");
JPanel panel = new JPanel(new GridLayout(3, 1));
// 输入面板
JPanel inputPanel = new JPanel();
inputPanel.add(new JLabel("数字1:"));
inputPanel.add(num1Field);
inputPanel.add(new JLabel("数字2:"));
inputPanel.add(num2Field);
// 按钮面板
JPanel buttonPanel = new JPanel();
buttonPanel.add(addBtn);
buttonPanel.add(subtractBtn);
buttonPanel.add(multiplyBtn);
buttonPanel.add(divideBtn);
// 结果面板
JPanel resultPanel = new JPanel();
resultPanel.add(resultLabel);
panel.add(inputPanel);
panel.add(buttonPanel);
panel.add(resultPanel);
frame.add(panel);
// 使用内部类作为事件监听器
CalculatorActionListener listener = new CalculatorActionListener();
addBtn.addActionListener(listener);
subtractBtn.addActionListener(listener);
multiplyBtn.addActionListener(listener);
divideBtn.addActionListener(listener);
}
// 内部类实现事件监听器 - 更好的代码组织
private class CalculatorActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
double num1 = Double.parseDouble(num1Field.getText());
double num2 = Double.parseDouble(num2Field.getText());
double result = 0;
// 根据按钮的文本来确定操作
String command = e.getActionCommand();
switch(command) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "×":
result = num1 * num2;
break;
case "÷":
if (num2 != 0) {
result = num1 / num2;
} else {
resultLabel.setText("不能除0!");
return;
}
break;
}
resultLabel.setText("结果: " + result);
} catch (NumberFormatException ex) {
resultLabel.setText("输入格式错误!");
}
}
}
private void addEventListeners() {
// 可以添加键盘事件等
}
public void show() {
frame.setVisible(true);
}
public static void main(String[] args) {
new CalculatorV2().show();
}
}
完整功能版本(使用Lambda表达式)
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BinaryOperator;
public class CalculatorV3 {
private JFrame frame;
private JTextField displayField;
private JLabel resultLabel;
private String currentOperator = "";
private double firstNumber = 0;
private boolean isNewNumber = true;
// 操作映射 - 使用Lambda表达式
private Map<String, BinaryOperator<Double>> operations = new HashMap<>();
public CalculatorV3() {
// 初始化操作映射 - 这里展示了Lambda表达式的简洁性
operations.put("+", (a, b) -> a + b);
operations.put("-", (a, b) -> a - b);
operations.put("*", (a, b) -> a * b);
operations.put("/", (a, b) -> b != 0 ? a / b : Double.NaN);
initializeGUI();
setupEventListeners();
}
private void initializeGUI() {
frame = new JFrame("科学计算器 V3");
frame.setSize(300, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
displayField = new JTextField();
displayField.setEditable(false);
displayField.setFont(new Font("Arial", Font.BOLD, 20));
displayField.setHorizontalAlignment(JTextField.RIGHT);
resultLabel = new JLabel(" ", SwingConstants.RIGHT);
resultLabel.setFont(new Font("Arial", Font.PLAIN, 14));
// 创建按钮
String[][] buttonLabels = {
{"7", "8", "9", "/"},
{"4", "5", "6", "*"},
{"1", "2", "3", "-"},
{"0", ".", "=", "+"},
{"C", "CE", "←", "±"}
};
JPanel buttonPanel = new JPanel(new GridLayout(5, 4, 2, 2));
for (String[] row : buttonLabels) {
for (String label : row) {
JButton button = new JButton(label);
button.setFont(new Font("Arial", Font.PLAIN, 16));
buttonPanel.add(button);
}
}
// 布局
frame.setLayout(new BorderLayout());
JPanel topPanel = new JPanel(new GridLayout(2, 1));
topPanel.add(displayField);
topPanel.add(resultLabel);
frame.add(topPanel, BorderLayout.NORTH);
frame.add(buttonPanel, BorderLayout.CENTER);
}
private void setupEventListeners() {
// 获取所有按钮
Component[] components = ((JPanel)frame.getContentPane()
.getComponent(1)).getComponents();
for (Component comp : components) {
if (comp instanceof JButton) {
JButton button = (JButton) comp;
String text = button.getText();
// 使用Lambda表达式注册事件监听器
button.addActionListener(e -> handleButtonClick(e));
}
}
// 也可以使用键盘快捷键
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(e -> {
if (e.getID() == KeyEvent.KEY_PRESSED) {
char keyChar = e.getKeyChar();
if (Character.isDigit(keyChar) ||
"+-*/.=".indexOf(keyChar) >= 0) {
handleKeyInput(String.valueOf(keyChar));
return true;
}
}
return false;
});
}
private void handleButtonClick(ActionEvent e) {
JButton source = (JButton) e.getSource();
handleInput(source.getText());
}
private void handleKeyInput(String input) {
handleInput(input);
}
private void handleInput(String input) {
switch(input) {
case "C":
clearAll();
break;
case "CE":
clearEntry();
break;
case "←":
backspace();
break;
case "±":
toggleSign();
break;
case "=":
calculate();
break;
case "+": case "-": case "*": case "/":
setOperator(input);
break;
default: // 数字和小数点
appendDigit(input);
break;
}
}
private void appendDigit(String digit) {
if (isNewNumber) {
displayField.setText(digit);
isNewNumber = false;
} else {
String current = displayField.getText();
if (digit.equals(".") && current.contains(".")) {
return; // 防止多个小数点
}
displayField.setText(current + digit);
}
}
private void setOperator(String operator) {
if (!displayField.getText().isEmpty()) {
firstNumber = Double.parseDouble(displayField.getText());
currentOperator = operator;
isNewNumber = true;
resultLabel.setText(firstNumber + " " + operator);
}
}
private void calculate() {
if (!currentOperator.isEmpty() && !displayField.getText().isEmpty()) {
double secondNumber = Double.parseDouble(displayField.getText());
// 使用Lambda表达式定义的操作
BinaryOperator<Double> operation = operations.get(currentOperator);
if (operation != null) {
double result = operation.apply(firstNumber, secondNumber);
if (Double.isNaN(result)) {
displayField.setText("错误: 除数不能为0");
} else {
displayField.setText(String.valueOf(result));
resultLabel.setText(firstNumber + " " +
currentOperator + " " + secondNumber + " =");
}
}
currentOperator = "";
isNewNumber = true;
}
}
private void clearAll() {
displayField.setText("");
resultLabel.setText("");
currentOperator = "";
firstNumber = 0;
isNewNumber = true;
}
private void clearEntry() {
displayField.setText("");
isNewNumber = true;
}
private void backspace() {
String text = displayField.getText();
if (text.length() > 0) {
displayField.setText(text.substring(0, text.length() - 1));
}
}
private void toggleSign() {
if (!displayField.getText().isEmpty()) {
double value = Double.parseDouble(displayField.getText());
displayField.setText(String.valueOf(-value));
}
}
public void show() {
frame.setVisible(true);
}
public static void main(String[] args) {
// 使用SwingUtilities确保线程安全
SwingUtilities.invokeLater(() -> {
new CalculatorV3().show();
});
}
}
关键概念总结
事件监听机制的三个核心组件:
// 1. 事件源 (Event Source) - 谁触发事件
JButton button = new JButton("点击我");
// 2. 事件对象 (Event Object) - 事件信息
// ActionEvent包含了事件的相关信息
// 3. 事件监听器 (Event Listener) - 如何处理事件
// 实现特定接口的对象
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 事件处理代码
}
});
五种监听器实现方式:
// 方式1: 匿名内部类 (最常用)
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("按钮被点击");
}
});
// 方式2: Lambda表达式 (Java 8+)
button.addActionListener(e -> System.out.println("按钮被点击"));
// 方式3: 方法引用
button.addActionListener(this::handleClick);
// 方式4: 内部类
class MyListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
handleClick(e);
}
}
// 方式5: 外部类
button.addActionListener(new ExternalActionListener());
事件处理的最佳实践:
// 1. 线程安全 - 使用SwingUtilities
SwingUtilities.invokeLater(() -> {
// UI更新代码
});
// 2. 避免长时间操作在事件线程
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
// 耗时操作
return null;
}
@Override
protected void done() {
// 更新UI
}
};
worker.execute();
// 3. 使用适配器类减少代码
window.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// 只重写需要的方法
}
});
这个计算器案例从最简单的版本开始,逐步增加了功能并展示了不同的事件处理方式,通过实践这些代码,你可以深入理解Java事件监听机制的工作原理和应用方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播