向ArrayList添加监听器

20

我有一个ArrayList,我动态地向其中添加一些对象,并且我有一个JButton。当程序运行时,ArrayList为空并且JButton被设置为setEnabled(false)。我想在ArrayList中有两个或更多元素时启用我的按钮,并在ArrayList只有一个项目或为空时再次禁用它。如何实现这一目标?


1
类似的:https://dev59.com/K3LYa4cB1Zd3GeqPTA8y - Joshua Goldberg
8个回答

17

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

这很棒。不需要新的类。 - christopher_pk

16

ArrayList 没有任何通知机制。

建议您编写自己的 List 实现,该实现委托给一个私有的 ArrayList 作为存储方式,但添加了监听通知的能力......或在 Java 中找到类似的东西。 DefaultListModel 可能 对您有用,尽管它本身未实现 List


11

正如@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);
    }
}

4

使用ArrayList无法实现这样的功能,因为正如@Jon Skeet所说,ArrayList没有任何类型的通知机制。您应该尝试使用JGoodies绑定ObservableList来解决问题。

或者您可以设置一个计时器,检查ArrayList的大小并相应地更改JButton。您需要在某个时间间隔内使用线程来监视列表。

或者,如果您知道所有添加/删除元素的位置,则在所有这些位置编写此登录。


4
如果您按照@Jon Skeet的建议编写自己的List实现,您可以为其提供一个EventListenerList。API概述了相关方法。

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

2

如果你只能使用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;
        }
    };
}

0

根据SimpleIntegerProperty语法,我创建了一个ArrayList,当其大小改变时触发。在这种情况下,您需要知道ArrayList的当前大小,因为您希望在大小为2时做出反应,因此解决方案很简单,只需执行以下操作:

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中添加比较,以便您知道何时添加或删除了某些内容。此外,您可以存储添加或删除的对象,并在监听器中使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接