6

次の Java Bean があるとします。

public class MyBean
{
    private List<String> names = new ArrayList<String>();

    public void addName(String name)
    {
        names.add(name);
        fireNamesPropertyChange(name);
    }
}

通常、コレクションのプロパティ変更イベントをどのように実装しますか? コレクションよりも配列に適していると思われる index プロパティを試してみますか?

4

8 に答える 8

11

:私は自分のいくつかの間違いに気付いた後にこの投稿を更新したので、これはオリジナルではなく、より洗練されたものです)

この目的のために、2つの新しいインターフェイスListListenerを作成してから、で定義された1つ(または複数)の関連メソッドの呼び出しですべてのメソッドをラップするListenableような新しいクラスを作成します。コードでは、次のようになります。ListenableArrayListListListListener

public class ListenableArrayList<T> extends ArrayList<T>
                                    implements Listenable<T> {

    private ArrayList<T> internalList;
    private ListListener<T> listener;

    /* .. */

    public void add(T item) {
        listener.beforeAdd(T item);
        internalList.add(item);
        listener.afterAdd(T item);
    }

    /* .. */

    public void setListener(ListListener<T> listener) {
        this.listener = listener;
    }

}

public interface ListListener<T> {
    /* .. */
    void beforeAdd(T item);
    void afterAdd(T item);
    /* .. */
}

public interface Listenable<T> {
    /* .. */
    void setListener(ListListener<T> listener);
    /* .. */
}

私がこのようにする理由は、ListenableArrayListを特定の実装に結び付けるのではなく、真にアドホックなリスナーをその場で作成できるようにするためです。たとえば、これを使用すると、次のことが可能になります。

Listenable<String> list = new ListenableArrayList<String>();

list.setListener(new ListListener<String>() {
    @Override
    public void beforeAdd(String item) {
        System.out.println("About to add element "+item+"...");
    }
    @Override
    public void afterAdd(String item) {
        System.out.println("...element "+item+" has been added.");
    }
});

少し雑然としていますが、一方で、コレクションやセットなどを簡単に拡張できるようになります。

于 2009-02-16T14:10:11.997 に答える
8

監視可能なコレクションをサポートしているGlazedListsライブラリをご覧ください。

自分でやる場合は、elementsAdded、elementsRemovedメソッド、または同様のメソッドを使用してカスタムリスナーインターフェイスを作成する可能性があります:-)(これも私のニーズに応じて)

于 2009-02-16T14:12:29.277 に答える
4

Observable Collection を使用できます: https://commons.apache.org/dormant/events/apidocs/org/apache/commons/events/observable/ObservableCollection.html

于 2009-02-16T15:18:28.260 に答える
2

JDK 7 以降のソリューション:

import javafx.collections.*;
import java.util.*;

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("s1");
        list.add("s2");

        ObservableList<String> observableList = FXCollections.observableList(list);
        observableList.addListener(new ListChangeListener<String>() {
            @Override
            public void onChanged(Change<? extends String> change) {
                while(change.next()){
                    System.out.println("added: " + change.getAddedSubList());
                }
            }
        });

        observableList.add("s3");
    }
}
于 2013-10-23T21:28:23.763 に答える
2

通常、私は次のことを行います。

public class MyBean {
    private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
    private List<String> names = new ArrayList<String>();
    public void addName(String name) {
        names.add(name);
        pcs.firePropertyChange("names", null, Collections.unmodifiableList(names));
    }
    public void addPropertyChangeListener(PropertyChangeListener l) {
        pcs.addPropertyChangeListener(l);
    }
    public void removePropertyChangeListener(PropertyChangeListener l) {
        pcs.removePropertyChangeListener(l);
    }
}

PropertyChangeSupport はリスナーを管理し、ユーザーに代わってイベントを発生させます。

null を「古い値」として渡すことにより、イベントが強制的に発生します。(とにかく、リスナーは古い値をあまり気にしない可能性があります)

于 2009-02-18T04:07:39.477 に答える
0

あなたが必要になると思いますfireNamesPropertyAddfireNamesProperyDelete。リストレベルの通知は、それが配列であり、削除を処理できないためにインデックスが追加された場合でも、IMHOは機能しません。あるインデックスの要素を変更できる場合は、も必要になりますfireNamesProperyChange。文字列値に加えて、パラメータとしてインデックスを使用すると便利な場合があります。

于 2009-02-16T13:57:05.287 に答える
0

あなたはおそらく探していjava.beans.PropertyChangeSupportますか?

私の意見では、あなたは避けるべきPropertyChangeEventです。IndexedPropertyChangeEventとにかく、Swing で使用されることはほとんどありません。タイプの焦点を絞り、 ajavax.swing.event.ChangeEventまたは類似のものを起動することをお勧めします (単に a を呼び出すだけでもRunnable)。

特定のタイプ (リストなど) については、Peter Štibraný による別の投稿で言及されている Glazed Lists (または同等のもの) が適しているようです。

于 2009-02-16T15:15:28.640 に答える
0

Swing GUI イベントの場合、通常はEventListenerListを使用して作業を行います。

編集:質問の言い換え: コレクションをどのように扱うのですか?私は通常、コレクションタイプに似たイベントを使用します。たとえば、TreeModel イベントは通常 TreePath 引数を取るか、マップ内の何かを示しますキー。

ただし、単純な JavaBeans の場合、最も一般的なのは、リスト/配列を想定してインデックスのみを使用することです。

于 2009-02-16T11:54:06.270 に答える