开发者

Add listener to ArrayList

开发者 https://www.devze.com 2023-03-17 02:11 出处:网络
I have an ArrayList which I add s开发者_运维百科ome Objects to it dynamically, and I have a JButton. The ArrayList is empty when running my program and the JButton is set to setEnabled(false). I want

I have an ArrayList which I add s开发者_运维百科ome Objects to it dynamically, and I have a JButton. The ArrayList is empty when running my program and the JButton is set to setEnabled(false). I want to enable my button whenever there are 2 elements in the ArrayList or more and disable it again if the ArrayList has one item or empty. How can I achieve this?


Javafx (part of JRE 8) provides an observable list implementation. This code works for me:

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 -> {
   ...
   });
}


ArrayList doesn't have any sort of notification mechanism.

I suggest you write your own List implementation which delegates to a private ArrayList for its storage, but adds the ability to listen for notifications... or find something similar within Java itself. DefaultListModel may work for you, although it doesn't implement List itself.


As @Jon Skeet suggests you can also do something like :

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


You can't do such thing with ArrayList because as @Jon Skeet says ArrayList doesn't have any sort of notification mechanism. You should try JGoodies binding ObservableList that could help.

Or you could set up a timer that will check for the size of ArrayList and change JButton accordingly. You will require a thread to do this job of monitoring list at some time interval.

Or if you know all the place where you add/remove elements from list then write this login at all that place.


If you write your own List implementation, as @Jon Skeet suggests, you can give it an EventListenerList. The API outlines the relevant methods.


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


If you need to fix this issue using only java.util.ArrayList you can use below solution. I don't know this is the exact solution you want. But you can achieve your need as below.

Implement what should happen after added and removed. Customize this interface as you needed.

public interface ListBehaviorHandler {

    void afterAdded();
    void afterDeleted();
}

And use below method to get custom behave list.

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;
        }
    };
}


Following SimpleIntegerProperty syntax I made an ArrayList which fire when the size change. In this case you need to now the current size of the ArrayList since you want to react when the size is 2, so a simple solution to this is doing the following:

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

In this case the observable is the size of the array, then, when declaring your arraylist, you can add a listener and act when the size is 2.

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

This implementation also allows you to add a comparison in the ChangeListener so you can know when there was something added or something removed. Also you can store the object added or removed and have it in the listener.

0

精彩评论

暂无评论...
验证码 换一张
取 消