3

WinRARのようなアーカイブを作成および抽出するためのJavaアプリケーションを開発しました。マルチスレッドを使用すると、同時に複数のアーカイブを作成できます。そして最近、アーカイブの作成中に、作成のたびに新しいJFrameにJProgressBarの形式で情報ステータスを追加したいと思いました。

しかし、私の問題は、アーカイブを作成する新しいステータスフレームとスレッドで情報を生成することです。そのため、現在プログレスバーを更新するためにアーカイブスレッドにJFrameを作成しています。

しかし、私がさまざまな情報源やあなたの回答/コメントでそれを読むことができたように、それはJavaSwingとパフォーマンスに反しています。EDT以外の場所でスイングオブジェクトを作成することはできません。

しかし、それでは、どうすれば問題を解決できますか?アーカイブの書き込みとそのステータスJFrame(JProgressBarを使用)の間の通信を確立するにはどうすればよいですか?


編集:

アプリケーションのGUIを管理するためにSwingWorkerを実装しました。これで完了です。別の質問があります。

SwingWorkerを使用して、ステータスフレームのボタンのイベントでバックグラウンドタスクを実行するにはどうすればよいですか?(例:圧縮を一時停止または停止します。)

4

3 に答える 3

5

他の人が示唆しているように、最良の方法はを使用することSwingWorkerです。

SwingWorkerプロパティはリッスン可能であり、リスナーは常にEDTで呼び出されるため、次のように実行できます。

public class ArchivingWorker extends SwingWorker<Void, Void> {
    JProgressBar progressBar = null;
    // Other members here...
    ...

    public ArchivingWorker(...) {
        // Any specific initialization here (in EDT)
        addPropertyChangeListener(new PropertyChangeListener() {
            @Override void propertyChange(PropertyChangeEvent e) {
                if (    "state".equals(e.getPropertyName())
                    &&  e.getNewValue() == StateValue.STARTED) {
                    // Background thread has just started, show a progress dialog here
                    progressBar = new JProgressBar();
                    ...
                }
                else if ("progress".equals(e.getPropertyName())) {
                    // Update progress bar here with e.getNewValue()
                    ...
                }
            }
        });
    }

    @Override protected Void doInBackground() {
        // Archiving process here and update progress from time to time
        setProgress(progress);

        return null;
    }

    @Override protected void done() {
        // Ensure that archiving process worked correctly (no exception)
        try {
            get();
        } catch (Exception e) {
            // Handle exception (user feedback or whatever)
        } finally {
            // Close progress dialog
            ...
        }
    }
}

次にArchivingWorker、必要に応じて使用できます。

ArchivngWorker worker = new ArchivingWorker(...);
worker.execute();
于 2011-09-21T15:23:23.863 に答える
5
  1. JProgressBarJDialogに入れて表示し、新しい最上位コンテナを作成しないでください。それを一度作成して再利用する

  2. 時間のかかる重いコードは、バックグラウンド タスクにリダイレクトする方が適切です。

  3. JProgressBarバックグラウンド タスクから進捗に応じて移動できます

    • GUI 関連のコードが EDT で実行される場合のみSwing でより多くの同時実行性

    • それを行うには2つの正しい方法があります

      • SwingWorkerを使用して

      • からRunnable#Threadですが、GUI 関連のコードは次のようにラップする必要があります。invokeLater()

于 2011-09-21T11:15:43.087 に答える
1

@mKorbelが提供する回答は問題ありませんがJDialog、プログレス バーを表示するために別のトップ レベル コンテナー ( a など) を使用する必要はありません。代わりに、インスタンスのGlass Paneを使用できます。JFrame

于 2011-09-21T12:02:17.467 に答える