歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Java基礎知識:GUI之事件處理

Java基礎知識:GUI之事件處理

日期:2017/3/1 9:10:41   编辑:Linux編程

  事件處理可以簡單地這麼理解,當有一個事件產生,程序要根據這個事件做出響應。比如,我們做了一個可以通過按鈕改變背景顏色的窗口,當我們點擊按鈕時便產生了一個事件,程序會根據這個事件來做出響應,也就是去改變背景的顏色。

運行結果

  那麼程序是怎樣做出響應的呢?這就需要事件監聽器ActionListener,這是一個接口,裡面包含了actionPerformed方法(也就是根據事件去執行的操作),所以我們要實現這個接口(實現接口裡的actionPerformed方法)做出一個監聽器對象出來,並且用按鈕來注冊這個監聽器對象,這樣當按鈕被點擊的時候,就會調用這個監聽器來執行響應了。

事件處理機制

  代碼(第42行開始為實現接口):

1 package buttonPanel;
2
3 import java.awt.*;
4 import java.awt.event.*; //事件監聽器接口ActionListener的位置。
5 import javax.swing.*;
6
7 public class ButtonFrame 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 ButtonFrame() {
13 setSize(DEFAULT_WIDTH,DEFAULT_HEIGHT);
14 setLocationByPlatform(true);
15
16 //構造按鈕
17 JButton redButton = new JButton("RED");
18 JButton yellowButton = new JButton("YELLOW");
19 JButton blueButton = new JButton("BLUE");
20
21 buttonPanel = new ButtonPanel();
22
23 //添加按鈕到面板
24 buttonPanel.add(redButton);
25 buttonPanel.add(yellowButton);
26 buttonPanel.add(blueButton);
27
28 add(buttonPanel);
29
30 //構造對應顏色的動作監聽器
31 ColorAction redAction = new ColorAction(Color.red);
32 ColorAction yellowAction = new ColorAction(Color.yellow);
33 ColorAction blueAction = new ColorAction(Color.blue);
34
35 //每個按鈕注冊對應的監聽器
36 redButton.addActionListener(redAction);
37 yellowButton.addActionListener(yellowAction);
38 blueButton.addActionListener(blueAction);
39 }
40
41 //為了方便調用buttonPanel,將ColorAction作為ButtonFrame的內部類。
42 private class ColorAction implements ActionListener {
43 private Color backgroundColor;
44 public ColorAction(Color c) {
45 backgroundColor = c;
46 }
47 public void actionPerformed(ActionEvent event) {
48 buttonPanel.setBackground(backgroundColor);
49 }
50 }
51
52 public static void main(String[] args) {
53 EventQueue.invokeLater(new Runnable() {
54 public void run() {
55 JFrame frame = new ButtonFrame();
56 frame.setTitle("ColorButton");
57 frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
58 frame.setVisible(true);
59 }
60 });
61 }
62 }
63
64 class ButtonPanel extends JPanel {
65 private static final int DEFAUT_WIDTH = 300;
66 private static final int DEFAUT_HEIGHT = 200;
67
68 @Override
69 protected void paintComponent(Graphics g) {
70 g.create();
71 super.paintComponent(g);
72 }
73
74 @Override
75 public Dimension getPreferredSize() {
76 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);
77 }
78 } ButtonFrame

  -------------------------------------------------------------------------------------------------------------------------

  在上述代碼中,為了方便監聽器調用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 }

Copyright © Linux教程網 All Rights Reserved