Swing/SwingWorker の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/SwingWorker へ行く。
- Swing/SwingWorker の差分を削除
--- category: swing folder: SwingWorker title: SwingWorkerを使った処理の中断と進捗状況表示 tags: [SwingWorker, JProgressBar, JTextArea, Animation] author: aterai pubdate: 2006-06-10T11:46:45+09:00 description: JDK 6で新しくなったSwingWorkerを使って、処理の中断や進捗状況の表示更新などを行います。 image: https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTT8xXI-cI/AAAAAAAAAlQ/ueJc6P4EJVg/s800/SwingWorker.png --- * 概要 [#summary] `JDK 6`で新しくなった`SwingWorker`を使って、処理の中断や進捗状況の表示更新などを行います。 #download(https://lh4.googleusercontent.com/_9Z4BYR88imo/TQTT8xXI-cI/AAAAAAAAAlQ/ueJc6P4EJVg/s800/SwingWorker.png) * サンプルコード [#sourcecode] #code(link){{ class Task extends SwingWorker<String, String> { @Override public String doInBackground() { System.out.println("doInBackground() is EDT?: " + EventQueue.isDispatchThread()); try { Thread.sleep(1000); } catch (InterruptedException ie) { return "Interrupted"; } int current = 0; int lengthOfTask = 120; //list.size(); int lengthOfTask = 120; // list.size(); publish("Length Of Task: " + lengthOfTask); publish("\n------------------------------\n"); while (current < lengthOfTask && !isCancelled()) { try { Thread.sleep(50); //doSomething(file = list(current)); Thread.sleep(50); // doSomething(file = list(current)); } catch (InterruptedException ie) { return "Interrupted"; } setProgress(100 * current / lengthOfTask); publish("."); current++; } publish("\n"); return "Done"; } } class RunAction extends AbstractAction { public RunAction() { super("run"); } @Override public void actionPerformed(ActionEvent evt) { System.out.println("actionPerformed() is EDT?: " + EventQueue.isDispatchThread()); final JProgressBar bar = new JProgressBar(); runButton.setEnabled(false); canButton.setEnabled(true); anil.startAnimation(); statusPanel.removeAll(); statusPanel.add(bar); statusPanel.revalidate(); bar.setIndeterminate(true); worker = new Task() { @Override protected void process(List<String> chunks) { System.out.println("process() is EDT?: " + EventQueue.isDispatchThread()); if (!isDisplayable()) { System.out.println("process: DISPOSE_ON_CLOSE"); cancel(true); return; } for (String message : chunks) { appendText(message); } } @Override public void done() { System.out.println("done() is EDT?: " + EventQueue.isDispatchThread()); if (!isDisplayable()) { System.out.println("done: DISPOSE_ON_CLOSE"); cancel(true); return; } anil.stopAnimation(); runButton.setEnabled(true); canButton.setEnabled(false); statusPanel.remove(bar); statusPanel.revalidate(); String text = null; if (isCancelled()) { text = "Cancelled"; } else { try { text = get(); } catch (InterruptedException | ExecutionException ex) { ex.printStackTrace(); text = "Exception"; } } appendText(text); } }; worker.addPropertyChangeListener(new ProgressListener(bar)); worker.execute(); } } class CancelAction extends AbstractAction { public CancelAction() { super("cancel"); } @Override public void actionPerformed(ActionEvent evt) { if (worker != null && !worker.isDone()) { worker.cancel(true); } worker = null; } } }} * 解説 [#explanation] `JDK 6`以前の`SwingWorker.java`から一部メソッド名が変更されていますが、基本的な使い方は一緒のようです。 - `JDK 6`以前の`SwingWorker.java`から一部メソッド名が変更されているが、基本的な使用方法は同じ - `SwingWorker#execute()`メソッドで処理が開始され、`SwingWorker#doInBackground()`メソッドがバックグラウンドのワーカースレッドで実行される - `EDT`で実行する必要のある処理(上記の例では処理中に`JTextArea`へのメッセージの書き出し)は、`SwingWorker#process()`メソッドをオーバーライドして`SwingWorker#publish()`メソッドで呼び出したり、`SwingWorker#firePropertyChange()`を使用する - `EDT`で実行する必要のある処理(上記の例では処理中に`JTextArea`へのメッセージの書き出し)は`SwingWorker#process()`メソッドをオーバーライドして`SwingWorker#publish()`メソッドで呼び出したり、`SwingWorker#firePropertyChange()`を使用する - プログレスバーの処理には`SwingWorker#setProgress(int)`が予め用意されているので、`SwingWorker#addPropertyChangeListener(ProgressListener)`を設定するだけで使用可能 - `SwingWorker#setProgress(int)`で設定できるのは`0`から`100`で固定 #code{{ protected final void setProgress(int progress) { if (progress < 0 || progress > 100) { throw new IllegalArgumentException("the value should be from 0 to 100"); } // ... }} - 実行中の処理のキャンセルは`SwingWorker#cancel(boolean)`メソッドで実行する -- キャンセルされたかどうかは`SwingWorker#isCancelled()`メソッドで判定可能 ---- 現在のスレッドがイベントディスパッチスレッド(以下`EDT`)かどうかを調べる`EventQueue.isDispatchThread()`を、このサンプルで使用すると以下のようになります。 - 現在のスレッドがイベントディスパッチスレッド(以下`EDT`)かどうかを調べる`EventQueue.isDispatchThread()`をこのサンプルで使用してテスト + `actionPerformed() is EDT?`: `true` -- 現在のスレッド(このサンプルでは`EDT`)でボタンを選択不可にしたり、`SwingWorker#execute()`を実行している + `doInBackground() is EDT?`: `false` -- ワーカースレッド(バックグラウンド)で重い処理を行い、`EDT`をブロックして停止状態にならないようにする + `process() is EDT?`: `true` + `done() is EDT?`: `true` -- `Swing`関連のすべての作業(例えば`JProgressBar`の進捗表示更新)は`EDT`で行う必要があるので、`process()`か`done()`メソッド内で実行する ---- `SwingWorker#process()`メソッド内などで`JPanel#isDisplayable()`を呼び、アプリケーション(`frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);`が設定されている)が終了している場合は、タスクを中断することで`SwingWorker`が生き残るのを防止しています。 - `SwingWorker#process()`メソッド内などで`JPanel#isDisplayable()`を呼び、アプリケーション(`frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);`が設定されている)が終了している場合は、タスクを中断することで`SwingWorker`が生き残るのを防止 * 参考リンク [#reference] - [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/SwingWorker.html SwingWorker (Java Platform SE 8)] //- [http://java.sun.com/developer/technicalArticles/javase/swingworker/ Improve Application Performance With SwingWorker in Java SE 6] - [http://www.oracle.com/technetwork/articles/javase/swingworker-137249.html Improve Application Performance With SwingWorker in Java SE 6] - [https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html Worker Threads and SwingWorker] - [[JTableのセルにJProgressBarを表示>Swing/TableCellProgressBar]] - [[SwingWorkerで複数のJProgressBarを使用する>Swing/TwoProgressBars]] - [[SwingWorkerの一時停止と再開>Swing/PauseResumeSwingWorker]] * コメント [#comment] #comment - %%以前の`SwingWorker`の使い方などは、[[Timerでアニメーションするアイコンを作成>Swing/AnimeIcon]]、[[Fileの再帰的検索>Swing/RecursiveFileSearch]]などのソースコードやリンク先を参考にしてみてください。%% [[Fileの再帰的検索>Swing/RecursiveFileSearch]]は、`JDK 1.6`の`javax.swing.SwingWorker`を使用するように変更しました。 -- &user(aterai); &new{2007-02-22 (木) 17:57:58}; -- [[Timerでアニメーションするアイコンを作成>Swing/AnimeIcon]]は %%https://swingworker.dev.java.net/ にある%% `JDK 1.6`からバックポートされた`org.jdesktop.swingworker.SwingWorker`を使用するように変更しました。 -- &user(aterai); &new{2009-12-17 (木) 01:47:38}; -- `java.net`が新しくなって結構時間が経ったけど、http://java.net/projects/swingworker から`jar`がダウンロードできない…。[http://download.java.net/maven/2/org/jdesktop/swing-worker/1.1/ maven2 のリポジトリ]から取得するしかない? -- &user(aterai); &new{2011-12-02 (金) 17:23:45}; -- 上記の`jar`は、`1.1`なので、`1.2`が必要なら、 ソースを取得して、`ant bundles` -- &user(aterai); &new{2011-12-02 (金) 17:38:31}; #comment