如何使用invokeLater将一些IO与UI同步

时间:2013-07-23 20:59:49

标签: java swing invokelater

在我的java应用程序中,我使用swing来实现UI。有一个名为 theButton 的按钮,它在以下及时步骤中参与了一些IO操作:

  1. 按钮最初的文字为“点击连接”
  2. 然后在连接操作开始之前我想要 theButton 读取 “正在连接......”
  3. 然后IO操作开始
  4. 完成IO操作 theButton 现在读取“已连接(单击以断开连接)”。

    • 问题
    • 我正在使用以下代码,但首先在IO启动之前,按钮的文本不会更改为“正在连接...”!以及按钮doenst实际上在IO启动之前被禁用!我该怎么办?
  5. -

    // theButton with text "Click to connect is clicked"
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
    public void run() {
    theButton.setText("Trying to connect...");
    theButton.setEnabled(false);// to avoid clicking several times! Some users cannot wait
    theButton.repaint();
    // doing some IO operation which takes few seconds
    theButton.setText("connected ( click to disconnect)");
    theButton.setEnabled(true);
    theButton.repaint();
    }
    });
    

1 个答案:

答案 0 :(得分:3)

你的问题在这里:

javax.swing.SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    theButton.setText("Trying to connect...");
    theButton.setEnabled(false);
    theButton.repaint();

    // doing some IO operation which takes few seconds // **********

    theButton.setText("connected ( click to disconnect)");
    theButton.setEnabled(true);
    theButton.repaint();
  }
});
  • 标有*******评论的代码正在EDT上运行,并将它冻结你的应用程序及其所有绘画。
  • 使用SwingWorker代替在后台线程中运行代码。
  • 请注意,不需要在ActionListener中使用invokeLater(...)代码,因为默认情况下此代码已在EDT上运行。
  • 还可以免除repaint()次来电,因为不需要这些电话而且他们没有帮助。
  • 将一个PropertyChangeListener添加到SwingWorker以监听完成后,然后重置JButton。

取而代之的是:

// code not compiled nor tested
javax.swing.SwingUtilities.invokeLater(new Runnable() {
  public void run() {
    theButton.setText("Trying to connect...");
    theButton.setEnabled(false);

    MySwingWorker mySwingWorker = new MySwingWorker();

    mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
      // listen for when SwingWorker's state is done
      // and reset your button.
      public void propertyChange(PropertyChangeEvent pcEvt) {
        if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
          theButton.setText("connected ( click to disconnect)");
          theButton.setEnabled(true);
        }
      }
    });

    mySwingWorker.execute();
  }
});

// code not compiled nor tested
public class MySwingWorker extends SwingWorker<Void, Void> {
  @Override
  public void doInBackground() throws Exception {
    // doing some IO operation which takes few seconds
    return null;
  }
}

请务必阅读:Concurrency in Swing