我在我的GUI中有一个下拉框,它显示了另一个类中ArrayList的内容。 新的对象可以添加到GUI中其他地方的ArrayList,所以我需要知道它何时更新,因此我可以刷新下拉菜单。从我可以收集的内容来看,我的两个选择是扩展ArrayList类以允许我将自己的changeListener添加到它,或者使包含所讨论的ArrayList的类可扩展。我应该使用Listener还是Observer?
这将是一个更合适的解决方案?
我在我的GUI中有一个下拉框,它显示了另一个类中ArrayList的内容。 新的对象可以添加到GUI中其他地方的ArrayList,所以我需要知道它何时更新,因此我可以刷新下拉菜单。从我可以收集的内容来看,我的两个选择是扩展ArrayList类以允许我将自己的changeListener添加到它,或者使包含所讨论的ArrayList的类可扩展。我应该使用Listener还是Observer?
这将是一个更合适的解决方案?
这两种方案在本质上是同根生的设计模式的实现(在“观察家报”的格局被定义)在前一种情况下,您将ArrayList本身设置为“可观察”,后者是使用数组列表“可观察”的域对象。
我的倾向是做后者:使域对象可观察。这主要是因为您可能最终还会有其他可能会改变的域对象(应该更新GUI)。如果它已经被观察到,那么您已经设置好了。
请注意,您不必严格延伸java.util.Observable
- 您可以在不这样做的情况下实现设计模式。
这似乎是最简单的方法,但感谢所有其他答案。 – Simonw 2009-04-13 18:18:42
在Java中的Observable
实现很少使用,并且不能与Swing良好地互操作。改为使用EventListener
。
尤其是有什么原因不延长AbstractListModel
甚至管理列表中的“其他地方的GUI”的内容时使用DefaultListModel
直接?然后您的组合框可以使用代理到相同的ListModel
实例的ComboBoxModel
,添加自己的实现来跟踪选择状态。
我想到的是这样的(但我没有测试它):
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); }
}
总是比延伸更喜欢构图(我的参考是有效的Java和我的个人经验)。扩展ArrayList只是一个承诺,你不会违反任何类的不变式。它还将您绑定到您正在扩展的特定列表实施。
您可以切换到使用GUI design pattern。或者构建一个有限的实现。
创建具有方法DrawXArrayList(其中X是一些meaningfull名称的GUI接口形式它具有ArrayList类型
创建一个名为GUIView新类的参数,具有至少两种方法:。UpdateXArrayList,和RegisterForm
当你初始化应用程序有GUI形式注册本身与类实现GUIView。让执行GUIView可见的窗体类。
当你的GUI形式的任何更新ArrayList中有它调用UpdateXArrayList作为它所做的最后一件事然后,实现GUIView的类中的UpdateXArrayList方法将调用DrawXArrayList传递更新后的数组列表。然后,实现GUIFormInterface的表单类中的DrawXArrayList将执行需要更新显示ArrayList的控件的步骤。
尽管与观察者和侦听器设置相比,这看起来像很多步骤。您可以更好地控制各种用户操作如何影响UI,然后控制观察者 - 监听器模式。此外,您在代码中记录了用户操作和UI更新之间的交互。
为什么不使用绑定?
http://wiki.eclipse.org/index.php/JFace_Data_Binding
绑定你的GUI窗口小部件到您的列表。变化将透明地在两个对象之间传播。一定要用适当的observable包装你的模型,比如WritableList(如果直接使用ArrayList)。
如果你可以添加新的JAR到应用程序,看看glazed Lists
你指的JComboBox?如果是这样,我会看看ComboBoxModel及其实现。 – Avrom 2009-04-14 20:37:30