2.2.3  管理监听器列表

如果我们正在创建我们自己的组件并且希望这些组件触发事件,我们需要维护一个要通知的监听器列表。如果监听器列表是用于AWT事件的,我们可以使用AWTEventMulticaster类用于列表管理。对于Swing库而言,如果事件并不是一个预定义的AWT事件类型,我们需要自己管理监听器列表。通过使用javax.swing.event包中的EventListenerList类,我们不再需要手动管理监听器列表,也无需担心线程安全。而且如果我们需要获取监听器列表,我们可以通过public EventLIstener[] getListener(Class listenerType)来请求Component,或者是类似于JButton的getActionListeners()方法的类型特定方法。这使得我们可以由一个内部管理列表中移除监听器,从而有助于垃圾回收。

AWTEventMulticaster类

无论我们是否意识到,AWTEventMulticaster类被AWT组件用来管理事件监听器列表。这个类实现了所有的AWT事件监听器(ActionListener, AdjustmentListener, ComponentListener, ContainerListener, FocusListener, HierarchyBoundsListener, HierarchyListener, InputMethodListener, ItemListener, KeyListener, MouseListener, MouseMotionListener, MouseWheelListener, TextListener, WindowFocusListener, WindowListener以及WindowStatListener)。无论何时我们调用组件的方法来添加或是移除一个监听器时,AWTEventMulticaster都会被用来作为支持。

如果我们希望创建我们自己的组件并且管理用于AWT事件/监听器对的监听器列表,我们可以使用AWTEventMulticaster。作为一个示例,我们来看一下如何创建一个通用组件,当按键在组件内部按下时,这个组件会生成一个ActionEvent对象。这个组件使用KeyEvent的public static String getKeyText(int keyCode)方法来将按键代码转换相应的文本字符串,并且将这个文本字符串作为ActionEvent的动作命令回传。因为这个组件是作为ActionListener观察者的源,他需要一对添加/移除方法来处理监听器的注册。这也就是AWTEventMulticaster类的用处所在,因为他会管理由我们的监听器列表变量中监听器的添加或移除:

private ActionListener actionListenerList = null;
public void addActionListener(ActionListener actionListener) {actionListenerList = AWTEventMulticaster.add(actionListenerList, actionListener);
}
public void removeActionListener(ActionListener actionListener) {actionListenerList = AWTEventMulticaster.remove(actionListenerList, actionListener);
}

类定义的其余部分描述了如何处理内部事件。为了向ActionListener发送击键需要注册一个内部的KeyListener。另外,组件必须能够获得输入焦点;否则,所有的击键都会到达其他的组件。完整的类定义如列表2-4所示。用于监听器通知的代码行以粗体显示。这一行通知所有的已注册的监听器。

/*** */
package swingstudy.ch02;import java.awt.AWTEventMulticaster;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;import javax.swing.JComponent;/*** @author lenovo**/
public class KeyTextComponent extends JComponent{private ActionListener actionListenerList = null;public KeyTextComponent() {setBackground(Color.CYAN);KeyListener internalKeyListener = new KeyAdapter() {public void keyPressed(KeyEvent event) {if(actionListenerList != null) {int keyCode = event.getKeyCode();String keyText = event.getKeyText(keyCode);ActionEvent actionEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, keyText);actionListenerList.actionPerformed(actionEvent);}}};MouseListener internalMouseListener = new MouseAdapter() {public void mousePressed(MouseEvent event) {requestFocusInWindow();}};addKeyListener(internalKeyListener);addMouseListener(internalMouseListener);}public void addActionListener(ActionListener actionListener) {actionListenerList = AWTEventMulticaster.add(actionListenerList, actionListener);}public void removeActionListener(ActionListener actionListener) {actionListenerList = AWTEventMulticaster.remove(actionListenerList, actionListener);}public boolean isFocusable() {return true;}
}

图2-5显示所有的组件。图中上部分是组件,而下底部则是一个文本输入框。为了显示按下键的文本字符串,向更新文本框的KeyTextComponent注册了一个ActionListener。

示例源码如列表2-5所示。

/*** */
package swingstudy.ch02;import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JFrame;
import javax.swing.JTextField;/*** @author lenovo**/
public class KeyTextTester {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubRunnable runner = new Runnable() {public void run() {JFrame frame = new JFrame("Key Text Sample");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);KeyTextComponent keyTextComponent = new KeyTextComponent();final JTextField textField = new JTextField();ActionListener actionListener =  new ActionListener() {public void actionPerformed(ActionEvent event) {String keyText = event.getActionCommand();textField.setText(keyText);}};keyTextComponent.addActionListener(actionListener);frame.add(keyTextComponent, BorderLayout.CENTER);frame.add(textField, BorderLayout.SOUTH);frame.setSize(300, 200);frame.setVisible(true);}};EventQueue.invokeLater(runner);}}

EventListenerList类

尽管AWTEventMulticaster类很容易使用,然而他却并不能用于管理自定义的事件监听器列表或是javax.swing.event中的Swing事件器。我们可以创建一个这个类的自定义扩展用于处理我们需要管理的每一种类型的事件监听器列表,或者我们可以将列表存储在一个如Vector或是LinkedList的数据结构中。尽管使用Vector或是LinkedList可以工作得很好,当我们使用这种方法时,我们需要考虑同步问题。如果我们没有正确的编写列表管理,监听器通知也许会发生错误的监听器集合。

为了简化这种情况,Swing组件库包含了一个特殊的事件监听吕地类,EventListenerList。这个类的一个实例可以管理一个组件的所有不同的事件监听器。为了演示这个类的用法,我们来看一下如何使用EventListenerList替换AWTEventMulticaster来重写前面的例子。注意,在这个特定例子中,使用AWTEventMulticaster类实际上是一种更为简单的解决方法。然而,想像一个类似的情况下,在这种情况下事件监听器并不是一个预定义的AWT事件监听器或者是我们需要维护多个监听器列表。

添加或是移除监听器类似于在前面的例子中AWTEventMulticaster所用的技术。我们需要创建一个合适的变量类型-这次是EventListenerList-同时定义添加与移除监听器方法。这两种方法之间的主要区别在于初始的EventListenerList并不为null,而另一个初始时则是null。首先必须创建一个到空的EventListenerList的引用。这避免了在后面多次检测null列表变量的需要。添加与移除监听器的方法也有一些不同。因为EventListenerList可以管理任意类型的监听器列表,当我们添加或是移除监听器时,我们必须提供起作用的监听器类类型。

EventListenerList actionListenerList = new EventListenerList();
public void addActionListener(ActionListener actionListener) {actionListenerList.add(ActionListener.class, actionListener);
}
public void removeActionListener(ActionListener actionListener) {actionListenerList.remove(ActionListener.class, actionListener);
}

这只留下了要处理的监听器通知。在这个类中并不存在通用方法来通知有事件发生的特定类型的监听器,所以我们必须创建我们自己的代码。fireActionPerformed(actionEvent)的调用将会替代前面例子中的actionListenerList.actionPerformed(actionEvent)。这行代码会以数据形式由列表中获取一份一个特定类型的所有监听器的拷贝(以线程安全方式)。然后我们需要在这个列表中循环并通知合适的监听器。

protected void fireActionPerformed(ActionEvent actionEvent) {EventListener listenerList[] = actionListenerList.getListeners(ActionListener.class);for (int i=0, n=listenerList.length; i

新的改进类的完整代码显示在列表2-6中。当使用EventListenerList类时,不要忘记这个类位于javax.swing.event包中。除了组件类的名字,测试程序并没有改变。
/*** */
package swingstudy.ch02;import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.EventListener;import javax.swing.JComponent;
import javax.swing.event.EventListenerList;/*** @author lenovo**/
public class KeyTextComponent2 extends JComponent{private EventListenerList actionListenerList = new EventListenerList();public KeyTextComponent2() {setBackground(Color.CYAN);KeyListener internalKeyListener = new KeyAdapter() {public void keyPressed(KeyEvent event) {if(actionListenerList != null) {int keyCode = event.getKeyCode();String keyText = event.getKeyText(keyCode);ActionEvent actionEvent = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, keyText);fireActionPerformed(actionEvent);}}};MouseListener internalMouseListener = new MouseAdapter() {public void mousePressed(MouseEvent event) {requestFocusInWindow();}};addKeyListener(internalKeyListener);addMouseListener(internalMouseListener);}public void addActionListener(ActionListener actionListener) {actionListenerList.add(ActionListener.class, actionListener);}public void removeActionListener(ActionListener actionListener) {actionListenerList.remove(ActionListener.class, actionListener);}public void fireActionPerformed(ActionEvent event) {EventListener[] listenerList = actionListenerList.getListeners(ActionListener.class);for(int i=0, n=listenerList.length; ipublic boolean isFocusable() {return true;}
}

Swing组件集合的事件处理(四)相关推荐

  1. Swing组件集合的事件处理(二)

    2.2 多线程的Swing事件处理 为了提高其效率并降低其复杂性,所有的Swing组件都被设计为非线程安全的.尽管这听起比较恐怖,他只是简单的意味着对Swing组件的所有访问需要由一个单一线程完成-- ...

  2. Java-GUI编程实战之管理系统 Day2【Swing(组件介绍、布局管理器、事件类及监听器类)、基础组件按钮和输入框的用法】

    视频.课件.源码[链接:https://pan.baidu.com/s/13ffqGDzH-DZib6-MFViW3Q 提取码:zjxs] Java-GUI编程实战之管理系统 Day1[项目开发流程. ...

  3. java swing 组件技术(上)

    2019独角兽企业重金招聘Python工程师标准>>> 第一次写自己的博客,明知道写得很水,还是努力去写了,希望踏出第一步之后,能有着更好的发展.这几天看了一些资料,总结了一下自己所 ...

  4. java 画笔跟swing组件_「软帝学院」:2019思维最清晰的java学习路线

    第一步 首先要做好学习前的准备工作:java语言一般用于大型的服务器程序开发,所有有必要了解如下内容:Unix开发环境Unix系统原理.Unix开发环境.Unix常用命令.熟练掌握Unix常用命令:熟 ...

  5. java Swing组件总结

    文章目录 Jframe JDialog JPanel和JScrollPane容器 文本组件 按钮组件 1.JCheckBox 2.JRadionButton JComboBox组件 菜单组件 1.下拉 ...

  6. java swing 控件_Java Swing组件

    一.        java swing 组件技术简介 1.swing的特性 l  是AWT的扩展,swing比AWT提供了更多的组件和外观 l  它是纯java代码编写(除了JFrame.JDial ...

  7. jtable如何从表格中定位_Java Swing组件编程之JTable表格用法实例详解

    本文实例讲述了Java Swing组件编程之JTable表格用法.分享给大家供大家参考,具体如下: 表格是GUI编程中使用较多,但也是最麻烦的一个控件之一.表格是用来显示二维数据,提供编辑,选择等功能 ...

  8. JAVA之Swing组件(常用)

    write:2022-3-28 文章目录 边框(Border) 文本框(JTextFied) 文本区域(JTextArea)与滚动面板(JScrollPane) 下拉列表(JComboBox) 菜单( ...

  9. (JAVA)使用swing组件模仿QQ界面+网络编程实现QQ消息传输

    直接贴当时的实验报告吧. 1.课程题目 模仿腾讯QQ实现一个即时聊天软件,可以进行好友管理以及私聊等功能. 1.1功能性分类 功能类别 功能名称.标识符 描述 用户信息 用户登陆 用户登陆 用户注册 ...

最新文章

  1. vss6 forgot admin password
  2. iredmail安装roundcube webmail插件
  3. java.net.inetaddress_java.net.InetAddress类的应用
  4. Qt中的模型视图设计模式
  5. Tensorflow yolov3 Intel Realsense D435 单摄像头下各模块识别时间测试
  6. 设计模式------观察者模式
  7. XSS(跨站脚本攻击)攻击与防御
  8. 今年颜宁在《自然》发表三篇论文仍归清华,网友:可惜以后不是了
  9. 理论基础 —— 排序 —— 鸡尾酒排序
  10. 高通发布 5G 基带芯片 X60:5nm 制程,2021 年上市
  11. 小窍门-在EXECL表中加入下拉列表
  12. 《云计算核心技术剖析》读书笔记之一
  13. 7628刷breed_我的刷breed机方法 一步一图超详细
  14. DW-办公自动化02(Excel)
  15. java权限管理面试_java shiro面试题
  16. JAVA基础面试题——继承
  17. 生活中常见的计算机网络知识
  18. python 二值化细化_Python OpenCV图像细化
  19. Opencv 中的向量类Vec
  20. 运放搭建的跟随电路作用与分析

热门文章

  1. Hanlp在java中文分词中的使用介绍
  2. 手写js的insertAfter
  3. 运营商认为虚拟化也难快速降低企业OPEX
  4. NSInputStream和NSMutableURLRequest-实现保存文件到服务器
  5. 找到一款牛B的vim插件
  6. windows installer清理实用工具
  7. Zend Studio 10正式版破解(2013-02-26更新)
  8. WCF方法拦截及OperationInvoker传递参数到WCF方法的实现
  9. javascript 生成一个一亿长度的随机数组,从中排列出最大的1000个项;
  10. 区块链应用和法律规范