Java漫游笔记-05-事件处理

核心概念

  • 监听器:实现特定监听接口的对象。
  • 事件源:能够注册监听器并发送事件的对象。

工作机制

  • 当事件发生时,事件源将事件对象传递给所有注册的监听器对象。
  • 监听器对象根据事件对象的信息决定如何响应。

注册监听器的几种方法

  • 容器本身实现 ActionListener 接口。
  • 使用 EventHandler.create() 方法。
  • 使用匿名类。
  • 使用普通内部类。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.EventHandler;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

// 方法 1 :实现 ActionListener 接口,将容器自身设计为监听器对象
public class ClickMe extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private JButton northBtn;
private JButton westBtn;
private JButton eastBtn;
private JButton southBtn;
private JButton centerBtn;
private static int hit = 0;

public ClickMe() {
super(new BorderLayout());
// 这种方式,下面 2 个按钮会共享 1 个监听器对象(容器自身)
northBtn = new JButton("点我点我");
northBtn.setPreferredSize(new Dimension(200, 50));
add(northBtn, BorderLayout.NORTH);
northBtn.addActionListener(this);
westBtn = new JButton("点我点我");
westBtn.setPreferredSize(new Dimension(200, 50));
add(westBtn, BorderLayout.WEST);
westBtn.addActionListener(this);

eastBtn = new JButton("点我点我");
eastBtn.setPreferredSize(new Dimension(200, 50));
add(eastBtn, BorderLayout.EAST);
// 方法 2 :这种方法可以实现动态的事件处理,相对灵活
eastBtn.addActionListener(EventHandler.create(ActionListener.class,
this, "ClickBtnAction"));

southBtn = new JButton("点我点我");
southBtn.setPreferredSize(new Dimension(200, 50));
add(southBtn, BorderLayout.SOUTH);
// 方法 3 :如果这个事件不具普遍性,可以使用匿名类
southBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
southBtn.setText("方法 3 点击:" + (++ClickMe.hit));
}
});

centerBtn = new JButton("点我点我");
centerBtn.setPreferredSize(new Dimension(200, 50));
add(centerBtn, BorderLayout.CENTER);
// 方法 4 :如果这个事件具有普遍性,可以使用普通内部类
centerBtn.addActionListener(new ClickBtnActionListener("方法 4 点击:"));
}

public void ClickBtnAction() {
eastBtn.setText("方法 2 点击:" + (++ClickMe.hit));
}

private class ClickBtnActionListener implements ActionListener {
private String prefix;
public ClickBtnActionListener(String prefix) {
this.prefix = prefix;
}
@Override
public void actionPerformed(ActionEvent e) {
centerBtn.setText(prefix + (++ClickMe.hit));
}
}

public void actionPerformed(ActionEvent e) {
// 如果是更复杂的情况,这里就难以避免 if - else if - else 之类的代码了
JButton btn = (JButton) e.getSource();
btn.setText("方法 1 点击:" + (++ClickMe.hit));
}

private static void createAndShowGui() {
// Frame 是最顶层的窗口
JFrame frame = new JFrame("Click Me");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ClickMe clickMe = new ClickMe();
frame.setContentPane(clickMe);
// 显示
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}