`
mylxiaoyi
  • 浏览: 327584 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[翻译]Swing组件集合的事件处理(四)

阅读更多

 

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 stub
 
        Runnable 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<n; i++) {
    ((ActionListener)listenerList[i]).actionPerformed(actionEvent);
  }
}
 
新的改进类的完整代码显示在列表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; i<n; i++) {
            ((ActionListener)listenerList[i]).actionPerformed(event);
        }
    }
 
    public boolean isFocusable() {
        return true;
    }
}
 

 

分享到:
评论

相关推荐

    Java Swing'组件集合

    本篇文章将深入探讨Java Swing组件集合,帮助初学者更好地理解和使用这些组件。 首先,Swing 提供了丰富的组件集,包括按钮(JButton)、文本框(JTextField)、标签(JLabel)、复选框(JCheckBox)、单选按钮...

    swing控件及事件

    Swing是Java Foundation Classes (JFC)的一部分,提供了丰富的组件集合,用于创建美观且功能强大的图形用户界面。其中,一些常见的Swing控件包括: 1. **JFrame**:作为窗口的基础,它是所有Swing应用的起点。在...

    swing组件的详细介绍

    1. **元件多样性**:Swing提供了比AWT更丰富的组件集合,包括树状视图(Treeviews)、图片按钮等,让开发者能创建更为复杂的用户界面。 2. **跨平台一致性**:Swing组件是轻量级的,它们不依赖于底层操作系统,从而...

    Java Swing 组件全演示

    它提供了丰富的组件集合,使得开发者可以创建复杂的、交互式的用户界面。在Java Swing组件全演示中,我们将深入探讨Swing的核心概念、组件和设计原则。 首先,Swing是基于AWT(Abstract Window Toolkit)的,但提供...

    几个漂亮的SWING组件(源代码)

    Java Swing 是Java GUI(图形用户界面...总的来说,通过研究这些源代码,开发者不仅可以学习到Swing组件的基本使用,还能了解到组件的定制、交互处理和界面设计的技巧,这对于提升Java桌面应用开发技能是非常有帮助的。

    Swing 组件大全

    综上所述,"Swing组件大全"不仅涵盖了Swing库中的所有核心组件,还涵盖了数据库操作、Excel文件处理和自定义布局管理,是学习和开发Swing应用的宝贵资源。通过深入理解和实践这些知识点,开发者可以构建出功能强大且...

    java swing组件例子

    通过深入学习和实践这个"java swing组件例子",你将能够熟练掌握如何使用Java Swing创建功能丰富的GUI应用程序,理解组件间的交互、事件处理机制以及布局管理的重要性和用法。同时,还能了解到如何通过自定义外观和...

    swing资料集合

    它可能涵盖了Swing组件的定制,如创建自定义外观和行为,以及如何利用模型-视图-控制器(MVC)模式来构建可维护的应用程序。源代码实例可能涉及到Swing的高级组件,如JTable、JTree和JList,以及如何与数据库进行...

    基于java的开源的Swing组件 JIDE.zip

    Java Swing组件库JIDE是一个强大的开发工具,专为Java开发者设计,用于构建功能丰富的桌面应用程序。JIDE提供了许多预构建的、高度可定制的Swing组件,极大地扩展了标准Java Swing的功能。这个开源项目旨在简化GUI...

    经典Swing事例集合

    Swing组件的一个重要特点是它们支持模型-视图-控制器(MVC)设计模式,使得代码结构更清晰,维护更容易。 1. **JFrame**: JFrame是顶级容器,常用于创建窗口应用程序。你可以添加各种组件到JFrame上,如菜单栏、...

    Java Swing 组件全演示源代码.rar_java swing_java 组件_java swing_java源代码_

    Java Swing 是Java GUI(图形用户界面)开发的重要库,它提供了丰富的组件集合,用于构建桌面应用程序。本资源“Java Swing 组件全演示源代码”包含了Java Swing中的各种组件的完整示例代码,可以帮助开发者深入理解...

    JAVA Swing常用组件

    在学习和使用Swing组件时,了解每个组件的属性、方法和事件处理机制非常重要。通过实例代码和案例分析,你可以更好地掌握如何创建功能丰富的桌面应用程序。提供的"Swing常用组件"资源很可能是包含各种示例代码的集合...

    Swing组件介绍(非常全)

    它是Java Foundation Classes (JFC) 的一部分,提供了一套丰富的组件集合,用于构建功能完善的用户界面。Swing在早期是为了弥补Java AWT(Abstract Window Toolkit)的不足而设计的,提供了更丰富的功能、更好的可...

    java-swing 实例集合及其源码

    通过分析这些实例,开发者可以深入理解Swing组件的使用、事件处理机制、自定义绘制方法以及如何将它们结合到实际项目中。这些源码实例为初学者提供了宝贵的实践资料,同时也为经验丰富的开发者提供了灵感和参考。

    jfc+swing—java基础类组件集

    它们提供了一套丰富的组件集合,使得开发者能够创建功能强大的桌面应用程序。Swing 是 JFC 的一部分,它扩展了 Java AWT(Abstract Window Toolkit)库,提供了更多的功能和更好的性能。 一、JFC 概述: Java ...

    java使用swing组件编写的简易计算器

    总的来说,这个"java使用swing组件编写的简易计算器"项目涵盖了Java GUI编程的基础,包括Swing组件的使用、事件处理、基本计算逻辑实现以及IDE的使用。通过这个项目,开发者可以深入理解Java Swing的原理和实践,...

    SWING资料大集合

    - **Java Desktop.org**:这个网站提供了大量的Swing组件集合和示例代码,对于开发者来说是一个不错的资源库。 - **ChinaJavaWorld论坛**:这个中文论坛也有关于Swing的讨论和技术交流,适合中文读者。 ### 性能...

    基于Swing组件编写华容道Java程序

    在本项目中,“基于Swing组件编写华容道...它不仅展示了Swing组件的使用,还涵盖了图形用户界面设计、事件处理、数据结构以及算法应用等多个IT领域的知识。这样的项目对于学习和提升Java GUI编程能力是非常有价值的。

    Swing组件+MySQL销售管理系统_java系统_swing系统mysql_java.zip

    首先,Swing是Java的标准GUI库,它提供了丰富的组件集合,如按钮、文本框、表格、菜单等,用于构建美观且功能强大的桌面应用。在销售管理系统中,Swing组件可以用来创建用户友好的界面,让用户能够方便地输入、查看...

    SWING—JAVA 基础类组件集

    标题和描述中提到的知识点是关于Java...总结来说,Swing是一个全面的用户界面工具包,它通过Java语言的纯粹性,提供了一套跨平台、模块化的用户界面组件集合。开发者利用Swing可以创建功能强大、界面美观的应用程序。

Global site tag (gtag.js) - Google Analytics