0

私の Java アプリケーションでは、swing を使用して UI を実装しています。 次のタイムリーな手順でいくつかの IO 操作に関与するtheButtonと呼ばれるボタンがあります。

  1. ボタンにはもともと「クリックして接続」というテキストがあります
  2. 次に、接続操作が開始される前に、theButtonに 「接続中...」と表示させたい
  3. その後、IO操作が開始されます
  4. IO操作が完了すると、ボタンに「接続済み (クリックして切断)」と表示されます。

    • 問題:
    • 次のコードを使用していますが、まず、IO が開始する前にボタンのテキストが「接続中...」に変わりません! 同様に、IOが開始する前にボタンが実際に無効になることはありません! ここで何をすべきですか?

--

// 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();
}
});
4

1 に答える 1

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 を使用します。
  • invokeLater(...)このコードはデフォルトで EDT で既に実行されているため、ActionListener の for コードを使用する必要がないことに注意してください。
  • 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

于 2013-07-23T21:05:09.707 に答える