16

我的 GUI 中有一个下拉框,它显示另一个类中 ArrayList 的内容。新对象可以在 GUI 的其他地方添加到 ArrayList,所以我需要知道它什么时候更新,所以我可以刷新下拉菜单。据我所知,我的两个选择是扩展 ArrayList 类以允许我向其中添加自己的 changeListener,或者使包含相关 ArrayList 的类扩展可观察。

哪个是更合适的解决方案?

4

6 回答 6

11

这两种解决方案本质上是相同根设计模式(由四人组定义的“观察者”模式)的实现。在前一种情况下,您使 ArrayList 本身“可观察”,在后一种情况下,您使域使用数组列表“可观察”的对象。

我倾向于做后者:使域对象可观察。这主要是因为您最终可能会更改有关域对象的其他内容(应为其更新 GUI。)如果它已经是可观察的,那么您已经设置好了。

请注意,您不必严格扩展java.util.Observable- 您可以在不这样做的情况下实现设计模式。

于 2009-04-13T17:56:33.093 回答
9

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

}
于 2009-04-13T17:55:17.930 回答
2

为什么不使用绑定?

http://wiki.eclipse.org/index.php/JFace_Data_Binding

将您的 GUI 小部件绑定到您的列表。更改将在两个对象之间透明地传播。请务必使用适当的可观察对象包装您的模型,例如 WritableList(如果直接使用 ArrayList)。

于 2009-04-13T18:58:42.380 回答
1

总是更喜欢组合而不是扩展(我的参考是有效的 java 和我的个人经验)。扩展 ArrayList 只是一个承诺,您不会违反任何类不变量。它还将您绑定到您正在扩展的特定列表实现。

于 2009-04-13T17:58:49.890 回答
0

您可以切换到使用GUI 设计模式。或者构建一个有限的实现。

创建一个具有 DrawXArrayList 方法的 GUI 表单界面(其中 X 是一些有意义的名称。它有一个 ArrayList 类型的参数

创建一个名为 GUIView 的新类。它至少有两个方法:UpdateXArrayList 和 RegisterForm

当您初始化您的应用程序时,让 GUI 表单向实现 GUIView 的类注册自身。使实现 GUIView 的类对表单可见。

当您的 GUI 表单中的任何内容更新数组列表时,它会调用 UpdateXArrayList 作为它所做的最后一件事。然后,实现 GUIView 的类中的 UpdateXArrayList 方法将依次调用 DrawXArrayList 并传递更新的数组列表。然后,实现 GUIFormInterface 的表单类中的 DrawXArrayList 将采取需要更新显示 ArrayList 的控件的步骤。

虽然与观察者和侦听器设置相比,这似乎是很多步骤。您可以更好地控制各种用户操作如何影响 UI,然后是观察者 - 侦听器模式。此外,您在代码中记录了用户操作和 UI 更新之间的交互。

于 2009-04-13T18:02:45.840 回答
0

如果您可以向应用程序添加一个新 jar,请查看 glazed Lists

于 2009-04-20T20:24:33.487 回答