我的 GUI 中有一个下拉框,它显示另一个类中 ArrayList 的内容。新对象可以在 GUI 的其他地方添加到 ArrayList,所以我需要知道它什么时候更新,所以我可以刷新下拉菜单。据我所知,我的两个选择是扩展 ArrayList 类以允许我向其中添加自己的 changeListener,或者使包含相关 ArrayList 的类扩展可观察。
哪个是更合适的解决方案?
我的 GUI 中有一个下拉框,它显示另一个类中 ArrayList 的内容。新对象可以在 GUI 的其他地方添加到 ArrayList,所以我需要知道它什么时候更新,所以我可以刷新下拉菜单。据我所知,我的两个选择是扩展 ArrayList 类以允许我向其中添加自己的 changeListener,或者使包含相关 ArrayList 的类扩展可观察。
哪个是更合适的解决方案?
这两种解决方案本质上是相同根设计模式(由四人组定义的“观察者”模式)的实现。在前一种情况下,您使 ArrayList 本身“可观察”,在后一种情况下,您使域使用数组列表“可观察”的对象。
我倾向于做后者:使域对象可观察。这主要是因为您最终可能会更改有关域对象的其他内容(应为其更新 GUI。)如果它已经是可观察的,那么您已经设置好了。
请注意,您不必严格扩展java.util.Observable
- 您可以在不这样做的情况下实现设计模式。
Java 中的Observable
实现很少使用,并且不能与 Swing 很好地互操作。改用一个EventListener
。
特别是,在管理“GUI 中的其他位置”列表的内容时,是否有理由不扩展AbstractListModel
甚至DefaultListModel
直接使用?然后您的组合框可以使用ComboBoxModel
委托给同一个ListModel
实例的 a,添加它自己的实现来跟踪选择状态。
我想到了这样的事情(但我没有测试过):
final class MyComboBoxModel
extends AbstractListModel
implements ComboBoxModel
{
private final ListModel data;
private volatile Object selection;
MyComboBoxModel(ListModel data) {
/*
* Construct this object with a reference to your list,
* which contents are managed somewhere else in the UI.
*/
this.data = data;
data.addListDataListener(new ListDataListener() {
public void contentsChanged(ListDataEvent evt) {
fireContentsChanged(this, evt.getIndex0(), evt.getIndex1());
}
public void intervalAdded(ListDataEvent evt) {
fireContentsChanged(this, evt.getIndex0(), evt.getIndex1());
}
public void intervalRemoved(ListDataEvent evt) {
fireContentsChanged(this, evt.getIndex0(), evt.getIndex1());
}
});
}
public void setSelectedItem(Object selection) {
this.selection = selection;
fireContentsChanged(this, 0, data.getSize() - 1);
}
public Object getSelectedItem() { return selection; }
public int getSize() { return data.getSize(); }
public Object getElementAt(int idx) { return data.getElementAt(idx); }
}
为什么不使用绑定?
http://wiki.eclipse.org/index.php/JFace_Data_Binding
将您的 GUI 小部件绑定到您的列表。更改将在两个对象之间透明地传播。请务必使用适当的可观察对象包装您的模型,例如 WritableList(如果直接使用 ArrayList)。
总是更喜欢组合而不是扩展(我的参考是有效的 java 和我的个人经验)。扩展 ArrayList 只是一个承诺,您不会违反任何类不变量。它还将您绑定到您正在扩展的特定列表实现。
您可以切换到使用GUI 设计模式。或者构建一个有限的实现。
创建一个具有 DrawXArrayList 方法的 GUI 表单界面(其中 X 是一些有意义的名称。它有一个 ArrayList 类型的参数
创建一个名为 GUIView 的新类。它至少有两个方法:UpdateXArrayList 和 RegisterForm
当您初始化您的应用程序时,让 GUI 表单向实现 GUIView 的类注册自身。使实现 GUIView 的类对表单可见。
当您的 GUI 表单中的任何内容更新数组列表时,它会调用 UpdateXArrayList 作为它所做的最后一件事。然后,实现 GUIView 的类中的 UpdateXArrayList 方法将依次调用 DrawXArrayList 并传递更新的数组列表。然后,实现 GUIFormInterface 的表单类中的 DrawXArrayList 将采取需要更新显示 ArrayList 的控件的步骤。
虽然与观察者和侦听器设置相比,这似乎是很多步骤。您可以更好地控制各种用户操作如何影响 UI,然后是观察者 - 侦听器模式。此外,您在代码中记录了用户操作和 UI 更新之间的交互。
如果您可以向应用程序添加一个新 jar,请查看 glazed Lists