事件處理可以簡單地這麼理解,當有一個事件產生,程序要根據這個事件做出響應。比如,我們做了一個可以通過按鈕改變背景顏色的窗口,當我們點擊按鈕時便產生了一個事件,程序會根據這個事件來做出響應,也就是去改變背景的顏色。
運行結果
那麼程序是怎樣做出響應的呢?這就需要事件監聽器ActionListener,這是一個接口,裡面包含了actionPerformed方法(也就是根據事件去執行的操作),所以我們要實現這個接口(實現接口裡的actionPerformed方法)做出一個監聽器對象出來,並且用按鈕來注冊這個監聽器對象,這樣當按鈕被點擊的時候,就會調用這個監聽器來執行響應了。
事件處理機制
代碼(第42行開始為實現接口):
1 package buttonPanel;-------------------------------------------------------------------------------------------------------------------------
在上述代碼中,為了方便監聽器調用buttonPanel,將ColorAction作為ButtonFrame的內部類。如果將ColorAction類獨立出去,需要將buttonPanel傳遞到ColorAction,實現如下:
1 package buttonPanel2;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6
7 public class ButtonFrame2 extends JFrame {
8 private ButtonPanel buttonPanel;
9 private static final int DEFAULT_WIDTH = 300;
10 private static final int DEFAULT_HEIGHT = 200;
11
12 public ButtonFrame2() {
13 setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
14 setLocationByPlatform(true);
15
16 JButton redButton = new JButton("RED");
17 JButton yellowButton = new JButton("YELLOW");
18 JButton blueButton = new JButton("BLUE");
19
20 buttonPanel = new ButtonPanel();
21
22 buttonPanel.add(redButton);
23 buttonPanel.add(yellowButton);
24 buttonPanel.add(blueButton);
25
26 add(buttonPanel);
27
28 //將此對象通過this傳到ColorAction的構造器。
29 ColorAction redAction = new ColorAction(this,Color.red);
30 ColorAction yellowAction = new ColorAction(this,Color.yellow);
31 ColorAction blueAction = new ColorAction(this,Color.blue);
32
33 redButton.addActionListener(redAction);
34 yellowButton.addActionListener(yellowAction);
35 blueButton.addActionListener(blueAction);
36 }
37
38 public void setButtonPanelsBackground(Color backgroundColor) {
39 buttonPanel.setBackground(backgroundColor);
40 }
41
42 public static void main(String[] args) {
43 EventQueue.invokeLater(new Runnable() {
44 public void run() {
45 JFrame frame = new ButtonFrame2();
46 frame.setTitle("ColorButton");
47 frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
48 frame.setVisible(true);
49 }
50 });
51 }
52 }
53
54 class ColorAction implements ActionListener {
55 private ButtonFrame2 buttonFrame;
56 private Color backgroundColor;
57
58 //通過構造器的方法把ButtonFrame2對象傳過來,這個對象包含了成員變量buttonPanel,以便對其更換背景色。
59 public ColorAction(ButtonFrame2 buttonFrame,Color c) {
60 this.buttonFrame = buttonFrame; //this.buttonFrame只是對象管理者,管理的還是ButtonFrame的對象frame。
61 backgroundColor = c;
62 }
63 public void actionPerformed(ActionEvent event) {
64 buttonFrame.setButtonPanelsBackground(backgroundColor);
65 //這是我們在ButtonFrame2中添加的新方法。
66 }
67 }
68
69 class ButtonPanel extends JPanel {
70 private static final int DEFAUT_WIDTH = 300;
71 private static final int DEFAUT_HEIGHT = 200;
72
73 public ButtonPanel() {
74 setBackground(Color.pink);
75 }
76
77 @Override
78 protected void paintComponent(Graphics g) {
79 g.create();
80 super.paintComponent(g);
81 }
82
83 @Override
84 public Dimension getPreferredSize() {
85 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);
86 }
87 }
ButtonFrame2
--------------------------------------------------------------------------------------------------------
代碼存在一個缺陷,就是在構造按鈕、添加按鈕到面板、構造相應顏色的監聽器和注冊監聽器的時候有代碼復制的情況,為了避免代碼復制,我們可以創建一個makeButton方法,把這些重復的操作包含在內,實現如下:
1 package buttonPanel3;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6
7 public class ButtonFrame3 extends JFrame {
8 private ButtonPanel buttonPanel;
9 private static final int DEFAULT_WIDTH = 300;
10 private static final int DEFAULT_HEIGHT = 200;
11
12 public ButtonFrame3() {
13 setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
14 setLocationByPlatform(true);
15
16 buttonPanel = new ButtonPanel();
17 add(buttonPanel);
18
19 makeButton("RED",Color.red);
20 makeButton("YELLOW",Color.yellow);
21 makeButton("BLUE",Color.blue);
22 }
23
24 //為了避免代碼重復,我們將重復的操作放在這個函數裡。
25 public void makeButton(String name,final Color bg) {
26 JButton button = new JButton(name);
27 buttonPanel.add(button);
28 button.addActionListener(new ActionListener() { //可以new一個接口出來,但是後面必須接花括號實現內部方法。
29 public void actionPerformed(ActionEvent event) {
30 buttonPanel.setBackground(bg);
31 }
32 });
33 }
34
35 public static void main(String[] args) {
36 EventQueue.invokeLater(new Runnable() {
37 public void run() {
38 JFrame frame = new ButtonFrame3();
39 frame.setTitle("ColorButton");
40 frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
41 frame.setVisible(true);
42 }
43 });
44 }
45 }
46
47 class ButtonPanel extends JPanel {
48 private static final int DEFAUT_WIDTH = 300;
49 private static final int DEFAUT_HEIGHT = 200;
50
51 @Override
52 protected void paintComponent(Graphics g) {
53 g.create();
54 super.paintComponent(g);
55 }
56
57 @Override
58 public Dimension getPreferredSize() {
59 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);
60 }
61 }
在代碼中,監聽器只被調用了一次,也就是在addActionListener()時。所以我們沒有必要為監聽器單獨做一個類出來,而是只需在用到監聽器時直接new一個ActionListener接口出來,並在花括號裡實現接口方法即可。
--------------------------------------------------------------------------------------------------------
但是有些程序員喜歡將因事件而改變的容器作為實現接口的監聽器,代碼如下,這樣會顯得混亂,我們不建議這麼做:
1 package buttonPanel4;
2
3 import java.awt.*;
4 import java.awt.event.*;
5 import javax.swing.*;
6
7 //將buttonPanel所在的ButtonFrame4實現接口。
8 public class ButtonFrame4 extends JFrame implements ActionListener {
9 private ButtonPanel buttonPanel;
10 private static final int DEFAULT_WIDTH = 300;
11 private static final int DEFAULT_HEIGHT = 200;
12
13 public ButtonFrame4() {
14 setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
15 setLocationByPlatform(true);
16
17 buttonPanel = new ButtonPanel();
18 add(buttonPanel);
19
20 makeButton("RED");
21 makeButton("YELLOW");
22 makeButton("BLUE");
23 }
24
25 public void makeButton(String name) {
26 JButton button = new JButton(name);
27 buttonPanel.add(button);
28 button.addActionListener(this);
29 //直接注冊this這個接口。
30 }
31
32 //覆蓋接口方法,String getActionCommand()為java.awt.event.ActionEvent的方法,返回動作事件相關的命令字符串,在這裡等於按鈕標簽。
33 //需要用到if else選擇語句。
34 @Override
35 public void actionPerformed(ActionEvent event) {
36 String c = event.getActionCommand();
37 if(c == "RED") {
38 buttonPanel.setBackground(Color.red);
39 }else if(c == "YELLOW") {
40 buttonPanel.setBackground(Color.yellow);
41 }else {
42 buttonPanel.setBackground(Color.blue);
43 }
44 }
45
46 public static void main(String[] args) {
47 EventQueue.invokeLater(new Runnable() {
48 public void run() {
49 JFrame frame = new ButtonFrame4();
50 frame.setTitle("ColorButton");
51 frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
52 frame.setVisible(true);
53 }
54 });
55 }
56 }
57
58 class ButtonPanel extends JPanel {
59 private static final int DEFAUT_WIDTH = 300;
60 private static final int DEFAUT_HEIGHT = 200;
61
62 @Override
63 protected void paintComponent(Graphics g) {
64 g.create();
65 super.paintComponent(g);
66 }
67
68 @Override
69 public Dimension getPreferredSize() {
70 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);
71 }
72 }