1

私は次のアプリケーションを持っています:

  • ユーザー入力用の1つのJTextField、
  • ビジー状態を示す1つのJLabel、
  • 検索結果を印刷するための1つのJTextArea。

ユーザーにテキストフィールドにテキストを書き込んで、Enterキーを押して結果を表示してほしい。私はこのようなリスナーを持っています:

private void searchForPattern(java.awt.event.ActionEvent evt) {
        textArea.setText("");
        busyLabel.setText("Searchnig ...");
        doSearch();
        busyLabel.setText("Idle");
    }

doSearchには、多くのXMLファイルを開いて特定のパターンを検索する非常に複雑なアルゴリズムがあり、時間がかかります。busyLabelのテキストは、doSearchが完了した後にのみSearching...に変更されます。doSearchには2番目のスレッドはなく、多くのIO操作のみがあります。

どうすればこれを修正できますか?

4

2 に答える 2

4

doSearchがSwingイベントスレッドを拘束している、古典的なSwing同時実行の問題(チュートリアル:Swingでの同時実行)があります。このスレッドは、Swingがすべてのペイント/描画とユーザーとの対話を行う場所であるため、完了するまでにかなりの時間がかかるコードに縛られた場合、アプリケーション全体が「フリーズ」し、コンポーネントが更新されず、すべてのユーザーが対話します。無視されます。

解決策:SwingWorkerオブジェクトによって提供されるようなバックグラウンドスレッドでそれを行います。done()SwingWorkerのメソッドのJLabelに「Idle」文字列を設定します。

すなわち、

private void searchForPattern(java.awt.event.ActionEvent evt) {
  textArea.setText("");
  busyLabel.setText("Searching ...");
  new SwingWorker<Void, Void>() {
     @Override
     protected Void doInBackground() throws Exception {
        doSearch();
        return null;
     }

     @Override
     protected void done() {
        busyLabel.setText("Idle");
     }
  }.execute();
}
于 2012-04-29T12:16:17.467 に答える
1

SwingUtilitiesのinvokeLaterメソッドを使用して、アプリケーションスレッドからGUIスイングコンポーネントを更新することもできます。

private void searchForPattern(java.awt.event.ActionEvent evt) {

  SwingUtilities.invokeLater(
    new Runnable(){
      public void run(){        
         textArea.setText("");
         busyLabel.setText("Searchnig ...");
      }
    }
  );

  doSearch();

  SwingUtilities.invokeLater(
    new Runnable(){
      public void run(){
         busyLabel.setText("Idle");
      }
    }
  );
}

PSの編集:ここでは、EDTからsearchForPattern()関数を呼び出していないことを前提としています。つまり、ActionListenerから呼び出す場合は、次のように呼び出す必要があります。

new Thread(
   new Runnable(){
      public void run(){
         searchForPattern(....)
      }
    }
  ).start();
于 2012-04-29T12:44:40.140 に答える