2

コントロールなどの一般的な機能を提供するいくつかのパネルを実装することがよくあります。このために、呼び出し元がコントロールにアタッチして変更に関する通知を取得できるように、リスナーを追加できるようにしたいと考えています。

これまでのところ、リスナーを保持する独自のものを単純に使用して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);
        }
    }
}

listenerListfromのメンバーJComponentに直接アクセスするのは、少し奇妙に感じます。しかし、これまでのところ、より良い方法は見つかりませんでした。また、これに新しいリスナーを追加するときは、以下のようにしますが、これが本当に適切な方法かどうかはわかりません。

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

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

だから私は知りたいのですが、listenerListリスナーを追加および削除する正しい方法でメンバーにアクセスしているので、他の標準コントロールと同じように動作しますか? またはbest practice、これをどのように行うべきか、これまで見逃していたものがありますか?

4

2 に答える 2

1

EventListenerListドキュメントに良い例があり、このConverter例では独自のlistenerListinを使用していConverterRangeModelます。

于 2013-07-16T10:57:23.850 に答える
1

Swings が GUI の作成に課す制限に注意してください。この方法で ** listenerlist ** にアクセスしても害はありません。これは最善のアプローチではないかもしれません。Swing はシングル スレッドであると想定されており、スレッド セーフではありません。

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

AddListener と RemoveListener は、EDT (イベント ディスパッチ スレッド) で呼び出す必要があります。 http://en.wikipedia.org/wiki/Event_dispatching_threadを参照してください。

getActionListeners を呼び出すときの Listenere の繰り返しについても参照してください。

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;   
}
于 2013-07-16T09:54:49.880 に答える