SwingWorker updating multiple comboboxes in multilpe panels

会有一股神秘感。 提交于 2019-12-08 02:13:53

问题


I have a little gui program that on startup reads data from an Excel file and some of these data need to go to the relevant comboboxes. I know how to do this by using a separate SwingWorker for each combobox:

public class ExcelReader extends SwingWorker<DefaultComboBoxModel, String> {

    private final DefaultComboBoxModel model;

    // Constructor called from a panel that has a combobox
    public ExcelReader(DefaultComboBoxModel model) {
        this.model = model;
    }

    @Override
    protected DefaultComboBoxModel doInBackground() throws Exception {

        ///// code to read data from Excel file
        ///// publish(someString) used here

        return model;
    }

    @Override
    protected void process(List<String> chunks) {

        for(String row : chunks)
            model.addElement(row);
    }
}

This works fine, but how can I use one SwingWorker class to fill multiple comboboxes? This would have the benefit of reading the file just once. Whenever something that needs to go to a combobox is found the relevant combobox is updated and then the program continues reading the next row until the end of the file.

So I tried to use boolean flags for the case that I want to update 2 comboboxes in one JPanel but this doesn't seem to work as expected. It's also not a good solution because in the future I'm planning to update more than 2 comboboxes in more than one panels.

public class ExcelReader extends SwingWorker<DefaultComboBoxModel[], String> {

    private boolean isData1 = false;
    private final DefaultComboBoxModel model1;
    private final DefaultComboBoxModel model2;
    private final DefaultComboBoxModel[] models = new DefaultComboBoxModel[2];

    // Constructor called from a panel that has 2 comboboxes
    public ExcelReader(DefaultComboBoxModel model1, DefaultComboBoxModel model2) {
        this.model1 = model1;
        this.model2 = model2;
    }

    @Override
    protected DefaultComboBoxModel[] doInBackground() throws Exception {

        ///// some code .....
        ///// some code .....

        // If data that needs to go to combobox1 is found
        if (someExpression)
            isData1 = true;

        publish(someString);

        ///// some code .....
        ///// some code .....

        models[0] = model1;
        models[1] = model2;

        return models;
    }

    @Override
    protected void process(List<String> chunks) {

        for (String row : chunks) {
            if (isData1) {
                model1.addElement(row);
                isData1 = false;
            }
            else
                model2.addElement(row);

    }
}

So how can only one SwingWorker be used to fill many comboboxes (that might be contained in different panels)?

By the way for the above examples I'm calling ExcelReader from one of my panels (class that extends JPanel). In the first case the panel calling the worker has only one combobox, the second has 2. While the first example works fine, is this the correct way to update the comboboxes in a gui or should the worker be called from somewhere else?


回答1:


  • Map your models to logical names, so you can attach data from excel to a logical part of the UI.
  • Pass to the worker the UI elements you'd like to interact with (the models, in this case)
  • Go off the UI thread ASAP (in this case the action) and let the SwingWorker sync the UI updates for you.
  • Let the SwingWorker batch updates for you, while mapping them to a logical function in your UI.

The codez:

import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

public class TestPanel extends JPanel {

    private TestPanel() {
        super();
        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

        Map<String, DefaultComboBoxModel> map = new HashMap<String,     DefaultComboBoxModel>();
        for (int i = 0; i < 5; i++) {
            JComboBox combo = new JComboBox();
            add(combo);
            map.put("combo" + i, (DefaultComboBoxModel) combo.getModel());
        }

        add(new JButton(new AbstractAction("fill me") {

            @Override
            public void actionPerformed(ActionEvent e) {
                new MyWorker(map).run();
            }
        }));

    }

    private class MyWorker extends SwingWorker<Void, String[]> {

        private final Map<String, DefaultComboBoxModel> map;

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

        @Override
        protected Void doInBackground() throws Exception {
            for (int i = 0; i < 20; i++) {
                String[] cell = new String[2];
                cell[0] = "combo" + i % 5;
                cell[1] = "value " + i;
                publish(cell);
            }
            return null;
        }

        @Override
        protected void process(List<String[]> chunks) {
            for (String[] chunk : chunks) {
                map.get(chunk[0]).addElement(chunk[1]);
            }
        }

    };

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the 
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        // Create and set up the window.
        JFrame frame = new JFrame("SwingWorker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new TestPanel();
        frame.setContentPane(panel);

        // Display the window.
        frame.setSize(200, 300);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}


来源:https://stackoverflow.com/questions/12028016/swingworker-updating-multiple-comboboxes-in-multilpe-panels

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!