SwingWorker在多面板中更新多个组合框 [英] SwingWorker updating multiple comboboxes in multilpe panels

查看:236
本文介绍了SwingWorker在多面板中更新多个组合框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小gui程序,启动时从Excel文件读取数据,其中一些数据需要去相关的组合框。我知道如何做到这一点,通过使用单独的SwingWorker每个组合框:

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

这很好,但是如何使用一个SwingWorker类来填充多个组合框?这将有一次读取文件的好处。每当发现需要转到组合框的相关组合框被更新,然后程序继续读取下一行,直到文件结束。

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.

所以我试过使用布尔标志的情况下,我想更新2个组合框中的一个JPanel,但这似乎没有按预期的工作。这也不是一个好的解决方案,因为在未来我打算在多个面板更新超过2个组合框。

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)?

顺便说一下,上面的例子我从一个面板调用ExcelReader扩展JPanel)。在第一种情况下,调用worker的面板只有一个组合框,第二个具有2.虽然第一个示例工作正常,这是更新gui中组合框的正确方法,还是应该从其他地方调用worker? p>

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?

推荐答案


  • 将模型映射到逻辑名称,因此可以将数据从excel附加到逻辑部分

  • 将UI元素(在这种情况下为模型)传递给工作者

  • 线程ASAP(在这种情况下为动作),并让 SwingWorker 为您同步UI更新。

  • SwingWorker 批量更新,同时将它们映射到UI中的逻辑函数。

    • 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.
    • 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();
                  }
              });
          }
      }
      

      这篇关于SwingWorker在多面板中更新多个组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆