【问题标题】:How to bind a List (one or more times)?如何绑定列表(一次或多次)?
【发布时间】:2011-11-26 04:52:33
【问题描述】:

我遵循演示模型模式对一些屏幕进行编码。

  • 我将一些 Bean 存储在 ArrayList
  • 感谢AbstractTableModel,我将在JTable 中显示此列表的内容
  • 我还想在组合框中(以表单形式)和其他一些在 JList 中显示此列表中的 一些记录,同时
  • 这三个屏幕(及其型号)相互独立

如何管理在我的列表中添加{一个或多个}/删除{一个或多个}并随时随地“实时”查看更改?

我即将编写自己的 ObservableList 或在 EventDispatcher 周围实现它......你怎么看?


PS:

  • 我知道在 C# 中 BindingList 有助于实现此目的,那么 Java 呢?
  • 感谢PropertyChangeSupport,我已经能够显示每个bean 的更新。

【问题讨论】:

  • 你应该看看 JGoodies 绑定,它基于 PresentationModel 模式,应该适合你的问题..

标签: java swing data-binding


【解决方案1】:

让您的AbstractTableModel 实现ListModel,它可以与JComboBox andJList 一起使用。您可以根据需要将方法转发到默认模型实现。

附录:SharedModelDemo,在How to Use Tables 中提到,是一个可以帮助您入门的示例。它extends DefaultListModel implements TableModel,而你应该这样做extends AbstractTableModel implements ListModel

附录:作为参考,这里是最小实现和三个测试实例的概述。我使用了默认的组合和列表实现,但如果需要,您可以使用相应的抽象实现。

public class SharedModel extends AbstractTableModel
        implements ComboBoxModel, ListModel {
    private ComboBoxModel comboModel = new DefaultComboBoxModel();
    private ListModel listModel = new DefaultListModel();

    //ComboBoxModel
    @Override
    public void setSelectedItem(Object anItem) {
        comboModel.setSelectedItem(anItem);
    }

    @Override
    public Object getSelectedItem() {
        return comboModel.getSelectedItem();
    }

    // ListModel
    @Override
    public int getSize() {
        return listModel.getSize();
    }

    @Override
    public Object getElementAt(int index) {
        return listModel.getElementAt(index);
    }

    @Override
    public void addListDataListener(ListDataListener l) {
        listModel.addListDataListener(l);
    }

    @Override
    public void removeListDataListener(ListDataListener l) {
        listModel.removeListDataListener(l);
    }

    // TableModel
    @Override
    public int getRowCount() {
        return 0;
    }

    @Override
    public int getColumnCount() {
        return 0;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        return null;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                SharedModel sm = new SharedModel();
                JTable table = new JTable(sm);
                JList list = new JList(sm);
                JComboBox check = new JComboBox(sm);
            }
        });
    }
}

【讨论】:

  • 我喜欢你的回答!你的建议是实施一种“瑞士刀”模式,是吗?但是,我是否必须将此共享模型注入代表每个屏幕的每个子模型?如果是,我必须另寻解决方案,因为每个屏幕都是在单独的模块中开发的。如果我在较低级别(在一个单独的模块中,对 javax.swing 没有任何依赖关系)实现“类似 ListModel”(ObservableList)并与所有屏幕共享,您怎么看?像这样,每个子模型都能收到添加/删除/更新通知?
  • 我不确定我是否理解。一个共享模型可以有任意数量的监听视图。 AbstractListModel 可以为JListJComboBox 提供事件处理,就像AbstractTableModelJTable 所做的那样。您的数据模型是分层的?
  • 如果我不够清楚,我很抱歉。所以,我关心的是保持每个屏幕和他们自己的模型分开。在我看来,如果我有一个带有JTable 的屏幕,我必须扩展一个AbstractTableModel 来“提供”JTable。如果我有另一个带有 JList 的屏幕(显示相同的数据),我会扩展一个专用的AbstractListModel。在较低级别上,AbstractTableModelAbstractListModel 都将在同一个“可观察列表”上监听事件(与摇摆完全分离)......也许我错了,请告诉我。 - 不,我的数据模型不是分层的。
  • 对,模型保持独立。我已经在上面概述了这样的SharedModel。它的单个实例可以传递给所有三个视图的构造函数:表、组合和列表。当然,您必须“填写”数据。
  • @Destroyica “所以,我关心的是保持每个屏幕和它们自己的模型分开”它们是否显示相同的数据(并允许“实时”更改):-)可以分享模型,事实上这就是模式的重点
【解决方案2】:

对于 JComboBox 和 JList,您可以使用 subList() 方法简单地引用 ArrayList 的部分。如果您可以轻松识别 ArrayList 中的开始和结束位置并且您需要的元素是连续的,那么这将起作用。

如果情况比这更动态,您可以实现自定义 List 类,该类在构造函数中采用 ArrayList,然后应用您需要返回适当记录的任何逻辑。

【讨论】:

  • 实际上,情况更加动态:我希望看到我的 JList 和我的 Combo Box 的内容“实时”变化,甚至更重要的是:必须更新每个条目的内容动态的。 subList() 是个好主意,但如果我删除一个条目会发生什么?我的原始列表将被更改,但不会通知 JTable,也不会引发 fireTableRowsDeleted
猜你喜欢
  • 2021-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-23
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多