• 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;
     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 }
    ButtonFrame4
  • 相关阅读:
    VMware虚拟机Mac OS X无法调整扩展硬盘大小,更新xcode时出现磁盘空间不足
    打包时Xcode报:此证书的签发者无效Missing iOS Distribution signing identity
    iPhone私有API
    Xcode真机调试中"There was an internal API error"错误解决方法
    用C#通过反射实现动态调用WebService 告别Web引用
    MySQL、PostgreSQL、Ingres r3、MaxDB等开源数据库的详细比较
    jQuery Mobile 移动开发中的日期插件Mobiscroll使用说明
    SQL Server 2008|2012 阻止保存要求重新创建表的更改
    SQL Server如何启用xp_cmdshell组件
    Windows平台下利用APM来做负载均衡方案
  • 原文地址:https://www.cnblogs.com/xingyazhao/p/5977934.html
Copyright © 2020-2023  润新知