Java中用得比较顺手的事件监听

       第一次听说监听是三年前,做一个webGIS的项目,当时对Listener的印象就是个“监视器”,监视着界面的一举一动,一有动静就触发对应的响应。

一、概述

      通过对界面的某一或某些操作添加监听,可以自发地调用监听函数/监听类,对操作作出反应。举个栗子:被监听的操作是“你惹你妈生气了”,添加的响应是“你妈给你爸打电话,你爸回家了,你爸打你一顿 ”。所以不管什么时候,只要“你惹你妈生气了”,都会触发这个操作的监听,最终结果是每次你都会被你爸打一顿。屡试不爽,无一例外。这就是事件监听,java.util.EventListener。

      Listener分很多种:ActionListener,MouseListener,PopMenuListener,windowListener等等。          

二、监听事件实现方式

1. 直接在控件中添加监听

如:给“保存按钮”添加ActionListener监听

1         saveCharaEditButton.addActionListener(new ActionListener() {
2             
3             @Override
4             public void actionPerformed(ActionEvent e) {
5                 // TODO Auto-generated method stub
6                 save();
7             }
8         });

2.写一个监听类,实现监听接口。

添加事件监听时只需要 添加这个监听类就ok了。【PS:这个内部类与函数并列写就可以,不用另建类文件,只是前面注意不要加public修饰符。默认只能有一个public类。】

 1     public JPanel setRightPanel(){
 2         JPanel rightPanel = new JPanel();
 3         double[][] size = {{15,TableLayout.FILL,30,TableLayout.FILL,35},{10,30,10,TableLayout.FILL}};
 4         rightPanel.setLayout(new TableLayout(size));
 5         JButton saveCharaEditButton = new JButton("保存编辑");
 6         JButton enableCharaEditButton = new JButton("启用编辑");
 7         rightPanel.add(enableCharaEditButton, "1,1");
 8         rightPanel.add(saveCharaEditButton, "3,1");
 9         rightPanel.add(setCharaJCTablePanel(), "0,3,4,3");
10         saveCharaEditButton.addActionListener(new saveEditToFloodCharacterValueListener());//添加监听
11         return rightPanel;
12     }
 1     class saveEditToFloodCharacterValueListener implements ActionListener{
 2 
 3         @Override
 4         public void actionPerformed(ActionEvent e) {
 5             // TODO Auto-generated method stub
 6             FloodCharacterValue floodCharacterValue = new FloodCharacterValue();            
 7             floodCharacterValue = FloodCharacterValue.transFldPropToFloodCharacterValue(editCharaFldprop);
 8             m_doc.m_floodExtractCharacterValue = floodCharacterValue;
 9         }
10     }

 3. 添加适配器,也可以实现监听。(其实方法同1)

    首先说一下适配器和监听接口的不同:new一个监听接口,需要重载该接口下面的所有方法,你删除任何一个,都会报错;但是适配器可以只重载你需要的那个方法。

以windowListener为例,给对话框dialog添加监听addWindowListerner,然后监听内容为窗口适配器WindowAdapter。对比如下:

(1)监听接口【默认重载所有方法,功能需求单一时不推荐】

                                        dialog.addWindowListener(new WindowListener() {
                                            @Override
                                            public void windowOpened(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                            @Override
                                            public void windowIconified(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                            @Override
                                            public void windowDeiconified(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                            @Override
                                            public void windowDeactivated(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                            @Override
                                            public void windowClosing(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                            @Override
                                            public void windowClosed(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                            @Override
                                            public void windowActivated(WindowEvent e) {
                                                // TODO Auto-generated method stub
                                            }
                                        });

(2)添加适配器【可以只重载需要的方法,功能单一时推荐】

 1     dialog.addWindowListener(new WindowAdapter() {
 2         @Override
 3         public void windowClosed(WindowEvent e) {
 4             // TODO Auto-generated method stub
 5             JDialog dialog2 = (JDialog) e.getSource();
 6             set_infoSectionList(update_infoSectionListByProp(prop));
 7             if (basinCheckList != null && !basinCheckList.isEmpty() && basinCheckList.get(0).getCHECKED()==1) {
 8                 tableCharaShowPanel.updateData(schemeType, get_infoSectionList(), false);            
 9             }else {
10                 tableCharaShowPanel.updateData(schemeType, get_infoSectionList(), true);            
11             }
12             super.windowClosed(e);
13             dialog2.dispose();
14         }
15     });

另外,关于添加哪些适配器,可以选择WindowAdapter,右键菜单中选择-resources-override/implement methods... - 勾选需要添加的方法即可。

4. 添加全局控件的监听

背景:leftSecTypeListrightSecTypeList,leftButtonrightButton 是this的全局控件变量。现在给他们添加鼠标点击监听.

这种操作一般分为两步:

(1)在初始化该控件的时候,添加参数为this的鼠标监听。

           leftSecTypeList.addMouseListener(this);

(2)重写mouseClicked(MouseEvent e)函数,根据e.getSource() 判断是触发鼠标点击的是哪个控件,给出相应的反应。

 1     public JPanel createSelPanel(){
 2         JPanel panel = new JPanel();  
*** 22 leftSecTypeList.addMouseListener(this); 23 rightSecTypeList.addMouseListener(this); 24 leftButton.addMouseListener(this); 25 rightButton.addMouseListener(this); 26 return panel; 27 }
 1     @Override
 2     public void mouseClicked(MouseEvent e) {
 3         // TODO Auto-generated method stub
 4         Object sourceObject = e.getSource();
 5         if (sourceObject == leftSecTypeList&& e.getClickCount() == 2) {
 6             HFSection section = leftSecTypeList.getSelectedItemType();
 9         }else if (sourceObject == rightSecTypeList&& e.getClickCount() == 2) {
10             HFSection section = rightSecTypeList.getSelectedItemType();
11         }else if (sourceObject == leftButton) {
12 
13         }else if (sourceObject == rightButton) {
14     
15         }
16     

 5.利用类AbstractButton的set/get动作命令。

Abstract直接已知子类:JButton, JMenuItem, JToggleButton

void     setActionCommand(String actionCommand)设置此按钮的动作命令。

string  getActionCommand() 返回此按钮的动作命令。

   //创建菜单Item的函数
   private JMenuItem createMenuItem(String text,String actionCommand) { JMenuItem item = new JMenuItem(text); item.setActionCommand(actionCommand);//设置此按钮的动作命令 item.addActionListener(new MenuActionListener()); return item; }
    //创建菜单
        private void initPopupMenu()
    {
        layerPopupMenu = new JPopupMenu();
        layerPopupMenu.add(createMenuItem("添加目录","addDir"));
        layerPopupMenu.add(createMenuItem("添加图层","addLayer"));
        layerPopupMenu.addSeparator();
        layerPopupMenu.add(createMenuItem("上移","up"));
        layerPopupMenu.add(createMenuItem("下移","down"));
    }    
    // 右键菜单操作命令
        class MenuActionListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            String actionCommand = e.getActionCommand();
            if(actionCommand.equals("addDir")){   addDir();}
            else if(actionCommand.equals("addLayer")){    addLayer();}
            else if(actionCommand.equals("up")){  layerUp();}
            else if(actionCommand.equals("down")){  layerDown();}
        }    

6. 以接口实现对按钮的监听响应

1.在工具条面板中:(1)定义响应接口 (2)以接口定义响应变量 (3)定义按钮,监听响应为变量

2.在调用文件中: 以implents方式实现 工具条面板中对应的接口变量

//1-1 ControlBarPanel.java 定义接口
    public interface IBackwardActionPerformed {
        public void ActionPerformed(ActionEvent e);
    }

//1-2 ControlBarPanel.java 以接口定义响应变量
public IBackwardActionPerformed backwardActionPerformed;

//1-3 ControlBarPanel.java 定义按钮,监听响应为变量
backwardButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        backwardActionPerformed.ActionPerformed(e);
    }
});

//2-1 MainForcastPanel.java 实现响应变量具体操作
controlBarPanel.backwardActionPerformed = new BackwardBtnActionListener();

//2-2 MainForcastPanel.java 实现响应变量具体操作
    class BackwardBtnActionListener implements IBackwardActionPerformed,Runnable {
        @Override
        public void ActionPerformed(ActionEvent e) {
            // TODO Auto-generated method stub
            Thread thread = new Thread(this);
            new HFProgressPane1(thread, "正在计算中......", null, null);
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            ************
        }
    }

 3. 方法6的详细代码

 1 public class ControlBarPanel extends JPanel implements ActionListener{
 2     private JButton jButton;
 3     public IActionPerformed iActionPerformed;
 4     
 5     public JPanel createPanel(){
 6         JPanel panel = new JPanel();
 7         panel.setLayout(new FlowLayout(FlowLayout.LEFT, 2, 0));
 8         jButton = new JButton("testButton");
 9         jButton.setMargin(new Insets(0, 0, 0, 0));
10         jButton.addActionListener(new ActionListener() {
11             @Override
12             public void actionPerformed(ActionEvent e) {
13                 // TODO Auto-generated method stub
14                 iActionPerformed.ActionPerformed(e);
15             }
16         });
17         panel.add(createForeTypePanel());
18         panel.add(jButton);
19         return panel;
20     }
21     
22     public interface IActionPerformed {
23         public void ActionPerformed(ActionEvent e);
24      }    
25 }
26 
27 public class ShowPanel extends JPanel {
28     private ControlBarPanel controlBarPanel;
29     //构造函数
30     public ShowPanel() {
31         controlBarPanel = new ControlBarPanel();
32         controlBarPanel.iActionPerformed = new ActionListener();
33         this.setLayout(new BorderLayout());
34         this.add(controlBarPanel,BorderLayout.NORTH);
35     }
36     
37     class ActionListener implements IActionPerformed{
38         @Override
39         public void ActionPerformed(ActionEvent e) {
40             // TODO Auto-generated method stub
41             function(e);
42         }
43     }    
44 }

7. 添加监听列表,然后通知所有监听。

分为三步

(1)定义变量:监听列表

(2)定义函数:注册监听,删除监听

(3)定义函数:通知所有监听

代码如下:

 1     /**
 2      * 拖动完成后监听保存队列
 3      */
 4     private List dragOverListenerList =new ArrayList();
 5     
 6     /**
 7      * 注册监听事件
 8      */
 9     public void addDragOverListener(DragOverListener listener){
10         synchronized (objSync) {
11             dragOverListenerList.add(listener);
12         }
13     }
14     
15     /**
16      * 删除监听
17      * @param eventObject
18      */
19     public void removeDragOverListener(DragOverListener listener){
20         synchronized (objSync) {
21             dragOverListenerList.remove(listener);
22         }
23     }
24     
25     /**
26      * 通知所有监听事件
27      */
28     private void notifyAllListener(){
29         for(int i=0;i<dragOverListenerList.size();i++)
30         {
31             ((DragOverListener)dragOverListenerList.get(i)).actionPerform(new DragOverEvent(this));
32         }
33     }
34     

在需要调用监听的地方,添加通知监听事件的函数即可。

四、小结

以上是一些Java事件监听与使用方法的一些介绍,属于入门级别。高级应用后期再予以学习与记录。

                                           写于2017年1月6日

原文地址:https://www.cnblogs.com/xujingbo/p/6253681.html