Welcome 微信登录

首页 / 操作系统 / Linux / Java基础知识:GUI之事件处理

事件处理可以简单地这么理解,当有一个事件产生,程序要根据这个事件做出响应。比如,我们做了一个可以通过按钮改变背景颜色的窗口,当我们点击按钮时便产生了一个事件,程序会根据这个事件来做出响应,也就是去改变背景的颜色。 运行结果  那么程序是怎样做出响应的呢?这就需要事件监听器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; 23 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 67 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 @Override78 protected void paintComponent(Graphics g) {79 g.create();80 super.paintComponent(g);81 }82 83 @Override84 public Dimension getPreferredSize() {85 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);86 }87 }ButtonFrame2  -------------------------------------------------------------------------------------------------------- 代码存在一个缺陷,就是在构造按钮、添加按钮到面板、构造相应颜色的监听器和注册监听器的时候有代码复制的情况,为了避免代码复制,我们可以创建一个makeButton方法,把这些重复的操作包含在内,实现如下: 1 package buttonPanel3; 23 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 67 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 @Override52 protected void paintComponent(Graphics g) {53 g.create();54 super.paintComponent(g);55 }56 57 @Override58 public Dimension getPreferredSize() {59 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);60 }61 } 在代码中,监听器只被调用了一次,也就是在addActionListener()时。所以我们没有必要为监听器单独做一个类出来,而是只需在用到监听器时直接new一个ActionListener接口出来,并在花括号里实现接口方法即可。 --------------------------------------------------------------------------------------------------------  但是有些程序员喜欢将因事件而改变的容器作为实现接口的监听器,代码如下,这样会显得混乱,我们不建议这么做:  1 package buttonPanel4; 23 import java.awt.*; 4 import java.awt.event.*; 5 import javax.swing.*; 67 //将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 @Override35 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 @Override63 protected void paintComponent(Graphics g) {64 g.create();65 super.paintComponent(g);66 }67 68 @Override69 public Dimension getPreferredSize() {70 return new Dimension(DEFAUT_WIDTH,DEFAUT_HEIGHT);71 }72 }本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-10/136341.htm