java - SwingWorker 使用一张 map 更新多个组合、列表、表格

标签 java swing hashmap swingworker

关注 previous问题已解决,我可以使用一个 HashMapSwingWorker 填充多个组合框。现在我想通过使用一张 map (如果可能)来填充/更新包含在 gui 应用程序的不同面板中的多个组合框和列表和表格。在 javadoc 中,我看到 DefaultListModelDefaultComboBoxModel 都扩展了 AbstractListModel,所以我将 Map 从

Map<String, DefaultComboBoxModel>

Map<String, AbstractListModel>

然后传递给 SwingWorker。以下代码有效,它可以通过使用这张 map 填充许多组合和列表。

中南合作:

public class TestPanel extends JPanel {

    private final Map<String, AbstractListModel> map = new HashMap<String, AbstractListModel>();

    private TestPanel() {
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        JComboBox combo1 = new JComboBox();
        JComboBox combo2 = new JComboBox();
        JList list1 = new JList(new DefaultListModel());
        JList list2 = new JList(new DefaultListModel());
        add(combo1);
        add(combo2);
        add(new JLabel("LIST 1:"));
        add(list1);
        add(new JLabel("LIST 2:"));
        add(list2);
        map.put("ComboBox1", (DefaultComboBoxModel)combo1.getModel());
        map.put("ComboBox2", (DefaultComboBoxModel)combo2.getModel());
        map.put("List1", (DefaultListModel)list1.getModel());
        map.put("List2", (DefaultListModel)list2.getModel());
        new MyWorker(map).run();
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setContentPane(new TestPanel());
                frame.setSize(200, 300);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private class MyWorker extends SwingWorker<Void, Object[]> {
        private final int COMBO_BOX_MODEL = 1;
        private final int LIST_MODEL = 2;
        private final Map<String, AbstractListModel> map;

        public MyWorker(Map<String, AbstractListModel> map) {
            this.map = map;
        }

        @Override
        protected Void doInBackground() throws Exception {
            // just a random way to fill the combos and the lists
            for (int i = 0; i < 20; i++) {
                Object[] cell = new Object[3];
                if (i>=0 && i<=4) {
                    cell[0] = "ComboBox1";
                    cell[1] = COMBO_BOX_MODEL;
                } else if (i>=5 && i<=9) {
                    cell[0] = "ComboBox2";
                    cell[1] = COMBO_BOX_MODEL;
                } else if (i>=10 && i<=14) {
                    cell[0] = "List1";
                    cell[1] = LIST_MODEL;
                } else if (i>=15 && i<=20) {
                    cell[0] = "List2";
                    cell[1] = LIST_MODEL;
                }
                cell[2] = "value " + i;
                publish(cell);
            }
            return null;
        }

        @Override
        protected void process(List<Object[]> chunks) {
            for (Object[] chunk : chunks) {
                if (chunk[1] == Integer.valueOf(COMBO_BOX_MODEL)) {
                    DefaultComboBoxModel model = (DefaultComboBoxModel)map.get(chunk[0]);
                    model.addElement(chunk[2]);
                }
                else if (chunk[1] == Integer.valueOf(LIST_MODEL)) {
                    DefaultListModel model = (DefaultListModel)map.get(chunk[0]);
                    model.addElement(chunk[2]);
                }
            }
        }
    };

}

问题 1:虽然上面的代码有效,但我不喜欢它的外观(特别是 process() 方法中的检查)。有没有更好和/或更聪明的方法来完成整个事情?

问题 2:有什么方法可以让 SwingWorker 通过使用一张 map 来更新表以及组合和列表?我找不到方法,因为 DefaultTableModel 扩展了 AbstractTableModel,它与 map 使用的 AbstractListModel 不同。

希望我说清楚了,如有任何帮助,我们将不胜感激。

最佳答案

  1. 毫无疑问,您的数据源具有与 Java 不同的类型系统;将这些类型与 Java 类型匹配的代码不会更漂亮,但至少您已经将它封装了。 enum 可能会有所帮助。

  2. 是的,您可以扩展 AbstractTableModel 并通过委托(delegate)给默认实现来实现其他接口(interface)。有大纲here .您必须决定这样的瓶颈在您的应用程序中是否有意义。

    public class SharedModel extends AbstractTableModel
        implements ComboBoxModel, ListModel
    

附录:另一种方法是编写三个模型(MyTableModelMyListModelMyComboBoxModel),每个模型都引用一个公共(public)数据模型。

Do you mean a common interface that is implemented by three models?

是的,一个由类实现的接口(interface),比如 ApplicationDataModel,它将数据库读入内部格式。然后,客户端模型可以向 ApplicationDataModel 请求每个实现其自己的接口(interface)契约所需的数据。

关于java - SwingWorker 使用一张 map 更新多个组合、列表、表格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12335165/

相关文章:

java - 堆栈 Pane 中的底部节点消失

java - Eclipse:可以使用 list 创建可运行的 .jar 吗?

java - 如何将 IntBinaryOperator 与 Java Swing 的 Switch Case 语句一起使用? (简单计算器)

java - setMnemonic() 并通过按键调用方法

java - java swing 中的全局加速器

python - 字典总是在 python 中存储哈希的最有效方式吗?

java - 如何检查是否加载了 log4j.properties?

java - Hibernate 计算属性和 SQL 查询

java - 为什么java泛型允许在HashMap<Integer,String>的get中传递 boolean 值

java - 为什么没有针对 ConcurrentHashMap 的 ConcurrentHashSet