【发布时间】:2011-09-28 12:42:59
【问题描述】:
我有一个 ArrayList,我动态地向它添加了一些对象,我有一个 JButton。运行我的程序时 ArrayList 为空,并且 JButton 设置为 setEnabled(false)。每当 ArrayList 中有 2 个或更多元素时,我想启用我的按钮,如果 ArrayList 有一个项目或为空,则再次禁用它。我怎样才能做到这一点?
【问题讨论】:
我有一个 ArrayList,我动态地向它添加了一些对象,我有一个 JButton。运行我的程序时 ArrayList 为空,并且 JButton 设置为 setEnabled(false)。每当 ArrayList 中有 2 个或更多元素时,我想启用我的按钮,如果 ArrayList 有一个项目或为空,则再次禁用它。我怎样才能做到这一点?
【问题讨论】:
ArrayList 没有任何通知机制。
我建议您编写自己的 List 实现,该实现委托给私有 ArrayList 进行存储,但增加了监听通知的能力......或在 Java 本身中找到类似的东西。 DefaultListModel 可能对你有用,虽然它本身没有实现 List。
【讨论】:
你不能用 ArrayList 做这样的事情,因为正如@Jon Skeet 所说,ArrayList 没有任何通知机制。您应该尝试 JGoodies 绑定 ObservableList,这可能会有所帮助。
或者您可以设置一个计时器来检查 ArrayList 的大小并相应地更改 JButton。您将需要一个线程在某个时间间隔内执行此监视列表的工作。
或者,如果您知道从列表中添加/删除元素的所有位置,则在所有位置写入此登录信息。
【讨论】:
如果您编写自己的List 实现,正如@Jon Skeet 建议的那样,您可以给它一个EventListenerList。 API 概述了相关方法。
【讨论】:
正如@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);
}
}
【讨论】:
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 -> {
...
});
}
【讨论】:
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);
}
}
});
【讨论】:
按照 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);
}
}
在这种情况下observable是数组的大小,那么,在声明你的arraylist时,你可以添加一个监听器,当大小为2时动作。
ArrayListProperty<Object> arrayList = new ArrayListProperty<>();
arrayList.addListener((ob, ov, nv) -> {
if(nv.intValue() == 2) doSomething();
});
此实现还允许您在 ChangeListener 中添加比较,这样您就可以知道何时添加了某些内容或删除了某些内容。您还可以存储添加或删除的对象并将其保存在侦听器中。
【讨论】:
如果您需要仅使用 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;
}
};
}
【讨论】: