web-dev-qa-db-ja.com

ArrayListにリスナーを追加する

動的にオブジェクトを追加するArrayListがあり、JButtonがあります。プログラムを実行すると、ArrayListが空になり、JButtonがsetEnabled(false)に設定されます。 ArrayListに2つ以上の要素がある場合は常にボタンを有効にし、ArrayListに項目が1つまたは空の場合はボタンを再度無効にしたい。どうすればこれを達成できますか?

19
Eng.Fouad

ArrayListには、通知メカニズムの種類はありません。

ストレージのためにプライベートListに委任するが、通知をリッスンする機能を追加する独自のArrayList実装を作成することをお勧めします...またはJava自体内で類似のものを見つけます。 DefaultListModelmayは機能しますが、List自体は実装していません。

13
Jon Skeet

Javafx(JRE 8の一部)は、監視可能なリストの実装を提供します。このコードは私にとってはうまくいきます:

ObservableList<MyAnno> lstAnno1 = FXCollections.observableList(new ArrayList<MyAnno>());

lstAnno1.addListener((ListChangeListener.Change<? extends MyAnno> c) -> {
   c.next();
   updateAnnotation((List<MyAnno>) c.getAddedSubList(), xyPlot);
});

...
lstAnno1.add(new MyAnno(lTs, dValue, strType));
...

public void updateAnnotation(List<MyAnno> lstMyAnno, XYPlot xyPlot) {
   lstMyAnno.forEach(d -> {
   ...
   });
}
15
Michael Baldauf

@Jon Skeetが示唆しているように、次のようなこともできます:

public class ListResponseModel<E> extends AbstractListModel {

    private static final long serialVersionUID = 1L;

    private ArrayList<E> delegate = new ArrayList<E>();

    @Override
    public int getSize() {
        return delegate.size();
    }

    @Override
    public Object getElementAt(int index) {
        return delegate.get(index);
    }

    public void add(E e){
        int index = delegate.size();
        delegate.add(e);
        fireIntervalAdded(this, index, index);
    }
}
10
Tapas Bose
ObservableList<DynamicObjects> ol = FXCollections.ObservableArrayList(new ArrayList<DynamicObjects>());
ListProperty lp = new SimplePropertyList(ol);

lp.addListener(new ChangeListener(){
        @Override public void changed(ObservableValue o, Object oldVal,
                                      Object newVal){
            if (ol.size() > 1 && !JButton.isEnabled()) {
                JButton.setEnable(true);
            } else if (ol.size < 2 && JButton.isEnabled()) {
                JButton.setEnable(false);
            }
    });
3
jdz

@Jon Skeetが言うように、ArrayListにはなんらかの通知メカニズムがないため、ArrayListを使用してそのようなことを行うことはできません。 JGoodiesバインディングObservableListを試してみてください。

または、ArrayListのサイズをチェックするタイマーを設定し、それに応じてJButtonを変更することもできます。この監視リストのジョブを一定の時間間隔で実行するには、スレッドが必要です。

または、リストから要素を追加/削除する場所がすべてわかっている場合は、その場所すべてにこのログインを書き込みます。

3
Harry Joy

@Jon Skeetが示唆するように、独自のList実装を作成する場合、 EventListenerList を指定できます。 APIは関連するメソッドの概要を示します。

3
trashgod

Java.util.ArrayListのみを使用してこの問題を修正する必要がある場合は、以下の解決策を使用できます。私はこれがあなたが望む正確な解決策であることを知りません。しかし、あなたは以下のようにあなたの必要性を達成することができます。

追加および削除後の動作を実装します。必要に応じて、このインターフェースをカスタマイズしてください。

public interface ListBehaviorHandler {

    void afterAdded();
    void afterDeleted();
}

以下のメソッドを使用して、カスタム動作リストを取得します。

public <E> List<E> getCustomList(ListBehaviorHandler listBehaviorHandler) {
    return new ArrayList<E>() {
        @Override
        public boolean add(E e) {
            boolean added = super.add(e);
            listBehaviorHandler.afterAdded();
            return added;
        }

        @Override
        public void add(int index, E element) {
            super.add(index, element);
            listBehaviorHandler.afterAdded();
        }

        @Override
        public E remove(int index) {
            E removed = super.remove(index);
            listBehaviorHandler.afterDeleted();
            return removed;
        }

        @Override
        public boolean remove(Object o) {
            boolean removed = super.remove(o);
            listBehaviorHandler.afterDeleted();
            return removed;
        }
    };
}
1
Chamly Idunil

SimpleIntegerProperty構文に従って、サイズが変更されたときに起動するArrayListを作成しました。この場合、サイズが2のときに反応したいので、ArrayListの現在のサイズを指定する必要があります。これに対する簡単な解決策は、次のとおりです。

ArrayListProperty.Java

public class ArrayListProperty<E> extends ArrayList<E> implements ObservableValue<Number> {
    private ExpressionHelper<Number> helper = null;
    private SimpleIntegerProperty sizeProperty;

    public ArrayListProperty(){
        super();
        sizeProperty = new SimpleIntegerProperty(0);
    }

    @Override
    public boolean add(E e) {
        boolean returnValue = super.add(e);
        sizeProperty.set(size());
        fireValueChangedEvent();
        return returnValue;
    }

    @Override
    public void add(int index, E element) {
        super.add(index, element);
        sizeProperty.set(size());
        fireValueChangedEvent();
    }

    @Override
    public E remove(int index) {
        E returnValue = super.remove(index);
        sizeProperty.set(size());
        fireValueChangedEvent();
        return returnValue;
    }

    @Override
    public boolean remove(Object o) {
        boolean returnValue = super.remove(o);
        if(returnValue){
            sizeProperty.set(size());
            fireValueChangedEvent();
        }
        return returnValue;
    }

    protected void fireValueChangedEvent(){
        ExpressionHelper.fireValueChangedEvent(helper);
    }

    @Override
    public void addListener(ChangeListener<? super Number> listener) {
        helper = ExpressionHelper.addListener(helper, sizeProperty, listener);
    }

    @Override
    public void removeListener(ChangeListener<? super Number> listener) {
        helper = ExpressionHelper.removeListener(helper, listener);
    }

    @Override
    public Number getValue() {
        return null;
    }

    @Override
    public void addListener(InvalidationListener listener) {
        helper = ExpressionHelper.addListener(helper, sizeProperty, listener);
    }

    @Override
    public void removeListener(InvalidationListener listener) {
        helper = ExpressionHelper.removeListener(helper, listener);
    }
}

この場合、オブザーバブルは配列のサイズです。次に、arraylistを宣言するときに、リスナーを追加して、サイズが2のときにアクションを実行できます。

ArrayListProperty<Object> arrayList = new ArrayListProperty<>();
arrayList.addListener((ob, ov, nv) -> { 
    if(nv.intValue() == 2) doSomething();
});

この実装では、ChangeListenerに比較を追加して、何かが追加または削除された時期を知ることもできます。また、追加または削除されたオブジェクトを保存して、リスナーに入れることもできます。

0
RodMendez