如何正确地将ActionListeren添加到自定义JComponent

时间:2013-07-16 09:28:18

标签: java swing listener actionlistener jcomponent

我经常实现一些面板,它们提供控件等常用功能。为此,我希望能够添加侦听器,以便调用者可以附加到控件并获取有关更改的通知。

到目前为止,我只使用自己的List来保存监听器,当我想触发一个动作时,我遍历列表并调用监听器。从外面看,它基本上看起来像任何其他Swing控件,但是我想知道这是否真的应该使用的方法。

特别是我想知道在循环中调用侦听器是否Swing本身也是如此,或者是否存在某种类型的队列来放置操作,以便Swing决定何时执行提供这样的行动。

当我研究这个时,我遇到了这个代码:

protected void fireActionPerformed(ActionEvent event)
{
    Object[] listeners = listenerList.getListenerList();
    ActionEvent e = null;

    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2)
    {
        if(listeners[i] instanceof ActionListener)
        {
            // Lazily create the event:
            if (e == null)
            {
                String actionCommand = event.getActionCommand();

                e = new ActionEvent(this,
                        ActionEvent.ACTION_PERFORMED,
                        actionCommand,
                        event.getWhen(),
                        event.getModifiers());
                e.setSource(event.getSource());
            }
            ((ActionListener)listeners[i+1]).actionPerformed(e);
        }
    }
}

来自listenerList的成员JComponent被直接访问,感觉有点奇怪。但到目前为止我还没有找到更好的方法。另外,在为此添加新的监听器时,我现在就像下面所示,但我不确定这是否真的是合适的方式:

public void addQueryListener(ActionListener oListener)
{
    listenerList.add(ActionListener.class, oListener);
}

public void removeQueryListener(ActionListener oListener)
{
    listenerList.remove(ActionListener.class, oListener);
}

所以我想知道,正在访问listenerList成员以正确的方式添加和删除侦听器,以便它们的行为与任何其他标准控件一样?或者是否有一些best practice应该如何做到这一点,到目前为止我还缺少这个?

2 个答案:

答案 0 :(得分:1)

记住Swings为创建gui所施加的限制。访问没有任何伤害 **听众列表**这样。可能这不是最好的方法。 Swing假设是单线程的,并且不是线程安全的。

http://codeidol.com/java/java-concurrency/GUI-Applications/Why-are-GUIs-Single-threaded/

需要在EDT上调用AddListener和RemoveListener(事件调度线程) 请参阅http://en.wikipedia.org/wiki/Event_dispatching_thread

另请参阅Listenere的迭代,即调用getActionListeners

它会创建一个ListenersList副本并返回

来自EventListenerList的代码

public <T extends EventListener> T[] getListeners(Class<T> t) {
Object[] lList = listenerList; 
int n = getListenerCount(lList, t); 
    T[] result = (T[])Array.newInstance(t, n); 
int j = 0; 
for (int i = lList.length-2; i>=0; i-=2) {
    if (lList[i] == t) {
    result[j++] = (T)lList[i+1];
    }
}
return result;   
}

答案 1 :(得分:1)

EventListenerList文档中有一个很好的示例,此Converter示例在listenerList中使用了自己的ConverterRangeModel