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

标签 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);
        }
    }
}

直接访问JComponent中的成员listenerList,感觉有点奇怪。但到目前为止我还没有真正找到更好的方法。另外,当添加一个新的监听器时,我现在这样做,如下所示,但我不确定这是否真的是合适的方式:

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

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

所以我想知道,访问listenerList成员是否是添加和删除监听器的正确方法,以便它们的行为像任何其他标准控件一样?或者是否有一些最佳实践应该如何完成,而我到目前为止还缺少这些?

最佳答案

请注意 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;   
}

关于java - 如何正确地将 ActionListeren 添加到自定义 JComponent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17672800/

相关文章:

带有监听器的 Android Broadcastreceiver

javascript - ExtJS监听器: anonymous function parameters

java - 希望创建一次性结合 Facebook 和电子邮件帐户的桌面应用程序 - 陷入第一个障碍?

java - 如何根据日期对HashMap进行排序?

java - 如何以最佳方式对 Hashmap 中的字母数字键进行排序?

Java Swing : JScrollPane not working

java - 当 SwingNode 的父级调整大小时,SwingNode 内容不调整大小

c - iOS:将对象添加为属性监听器时,是否必须在释放对象之前将监听器设置为 "unregister"?

java - 低延迟 Flink 流连接

java - 双击并使用库 ftp4j 传输文件