1

バックグラウンドでファイルを読み取って処理するSwingWorkerがあります。その後、JTextPaneでさまざまなスタイルのデータをフォーマットして表示します。

ファイルが大きい場合(200Kを超える場合)、プログレスバー付きのダイアログを表示します。SwingWorkerのdone()メソッドで、JTextPaneにデータを入力してから、ダイアログを非表示にします。done()メソッドは次のようになります。

protected void done() {
   populateTextPane();

   hideProgressDialog();
   System.out.println("After hideProgressDialog");
}

実行すると、ダイアログが消え、コンソールにprintlnメッセージが表示されますが、GUIがさらに10〜15秒間フリーズし、そのフリーズの最後にデータがJTextPaneに表示されます。

done()メソッドで起こったことはすべて、イベントディスパッチスレッドで行われると思いました。しかし、どうやらJVMは別のスレッドを生成してダイアログを非表示にし、JTextPaneにデータを入力している間にprintlnを実行しているようです。GUIがユーザー入力を再び受け入れる準備ができるまで進行状況ダイアログを表示したままにしたい...done()のすべてが本当に完了したことを検出するにはどうすればよいですか?

4

2 に答える 2

6

doneメソッドはEDTで実行されます。これに疑問がある場合は、EventQueue.isDispatchThread()メソッドを使用していつでもこれを確認できます。

考えられる理由は、このメソッドがEDTpopulateTextPane()での再描画をスケジュールしていることです。JTextPaneこれは、UIdone()にメソッドの結果が表示される前に、メソッドが終了したことを意味します。populateTextPane()

done次のようにメソッドを書き直すことができます

protected void done() {
   populateTextPane();
   SwingUtilities.invokeLater( new Runnable(){
     @Override
     public void run(){
       hideProgressDialog();
       System.out.println("After hideProgressDialog");
     }
   } );
}

これにより、EDTでhideProgressDialog可能なスケジュールの後にのみが実行されるようRunnablepopulateTextPane()なります。ただし、これでもUIが10〜15秒間フリーズします。唯一の違いは、進行状況ダイアログが引き続き表示されることです。

進行状況ダイアログがの上部に表示されている場合、これが機能するかどうかはわかりませんJTextPane。は、ダイアログが非表示になっRepaintManagerた後でのみ再描画することを決定する場合がありますJTextPane(したがって、は非表示ではなくなりJTextPaneます)。

于 2013-03-24T22:40:35.690 に答える
1

PopulateTextPaneは、EDTで長時間実行されるプロセスのように聞こえますが、これは望ましくありません。分割してみてください:SwingWorkerには、中間結果の公開をサポートするAPIがあります。

何かのようなもの

@Override
public Void doInBackground() throws Exception {
    ...
    while (!reader.isReady()) {
        publish(reader.readLine());
    }
    return null;
}

@Override
protected void process(List<String> lines) {
    for(String line: lines) {
        textPane.append(line);
    }
}
于 2013-03-25T08:20:46.357 に答える