Swing/SwingWorker のバックアップの現在との差分(No.8)
TITLE:SwingWorkerを使った処理の中断と進捗状況表示
Posted by terai at 2006-06-10
SwingWorkerを使った処理の中断と進捗状況表示
JDK 6 で新しくなった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:
概要
JDK 6
で新しくなったSwingWorker
を使って、処理の中断や進捗状況の表示更新などを行います。
- &jnlp;
- &jar;
- &zip;
Screenshot
Advertisement
#screenshot
サンプルコード
#spanend
#spanadd
class Task extends SwingWorker<String, String> {
#spanend
@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();
publish("Length Of Task: " + lengthOfTask);
publish("\n------------------------------\n");
#spandel
**サンプルコード [#p4592f3b]
#spanend
#spandel
#code{{
#spanend
#spandel
class RunAction extends AbstractAction{
#spanend
while (current < lengthOfTask && !isCancelled()) {
try {
Thread.sleep(50); // doSomething(file = list(current));
} catch (InterruptedException ie) {
return "Interrupted";
}
setProgress(100 * current / lengthOfTask);
publish(".");
current++;
}
publish("\n");
return "Done";
}
#spanadd
}
#spanend
#spanadd
#spanend
#spanadd
class RunAction extends AbstractAction {
#spanend
public RunAction() {
super("run");
}
public void actionPerformed(ActionEvent evt) {
//assert EventQueue.isDispatchThread();
System.out.println("actionPerformed() is EDT?: "
+ EventQueue.isDispatchThread());
final JProgressBar bar = new JProgressBar(0, 100);
#spanadd
#spanend
@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);
icon.animationStart();
anil.startAnimation();
statusPanel.removeAll();
statusPanel.add(bar);
statusPanel.revalidate();
bar.setIndeterminate(true);
worker = new SwingWorker<String, String>() {
@Override
public String doInBackground() {
System.out.println("doInBackground() is EDT?: "
+ EventQueue.isDispatchThread());
try { // dummy task
Thread.sleep(1000);
}catch(InterruptedException ie) {
return "Interrupted";
#spanadd
#spanend
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;
}
int current = 0;
int lengthOfTask = 120; //list.size();
publish("Length Of Task: " + lengthOfTask);
publish("------------------------------");
while(current<lengthOfTask && !isCancelled()) {
try { // dummy task
Thread.sleep(50);
}catch(InterruptedException ie) {
return "Interrupted";
}
setProgress(100 * current / lengthOfTask);
//worker.firePropertyChange("progress", current, current+1);
current++;
for (String message : chunks) {
appendText(message);
}
return "Done";
}
@Override
protected void process(java.util.List<String> chunks) {
//assert EventQueue.isDispatchThread();
System.out.println("process() is EDT?: "
+ EventQueue.isDispatchThread());
for(String message : chunks) {
appendLine(message);
#spanadd
#spanend
@Override public void done() {
System.out.println("done() is EDT?: " + EventQueue.isDispatchThread());
if (!isDisplayable()) {
System.out.println("done: DISPOSE_ON_CLOSE");
cancel(true);
return;
}
}
@Override
public void done() {
//assert EventQueue.isDispatchThread();
System.out.println("done() is EDT?: "
+ EventQueue.isDispatchThread());
icon.animationStop();
anil.stopAnimation();
runButton.setEnabled(true);
canButton.setEnabled(false);
statusPanel.remove(bar);
statusPanel.revalidate();
String text = null;
if(isCancelled()) {
if (isCancelled()) {
text = "Cancelled";
}else{
} else {
try {
text = get();
}catch(Exception ex) {
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
text = "Exception";
}
}
appendLine(text);
appendText(text);
}
};
worker.addPropertyChangeListener(new ProgressListener(bar));
worker.execute();
}
}
#spandel
class CancelAction extends AbstractAction{
#spanend
#spanadd
class CancelAction extends AbstractAction {
#spanend
public CancelAction() {
super("cancel");
}
@Override
public void actionPerformed(ActionEvent evt) {
if(worker!=null && !worker.isDone()) {
#spanadd
#spanend
@Override public void actionPerformed(ActionEvent evt) {
if (worker != null && !worker.isDone()) {
worker.cancel(true);
}
worker = null;
}
}
View in GitHub: Java, Kotlin解説
以前のSwingWorker.javaから一部メソッド名が変更されていますが、基本的な使い方は一緒のようです。- SwingWorker#execute()メソッドで処理が開始され、SwingWorker#doInBackground()メソッドが、バックグラウンドのスレッドで実行されます。
- EDTで実行する必要のある処理(上記の例では処理中にJTextAreaへのメッセージの書き出し)は、SwingWorker#process()メソッドをオーバーライドしてSwingWorker#publish()メソッドで呼び出したり、SwingWorker#firePropertyChange()を使えば良いようです。
- プログレスバーの処理には、SwingWorker#setProgress(int)が予め用意されているので、SwingWorker#addPropertyChangeListener(ProgressListener)を設定するだけで使用することが出来ます。
- 実行中の処理のキャンセルは、SwingWorker#cancel(boolean)メソッドで行います。キャンセルされたかどうかは、SwingWorker#isCancelled()メソッドで知ることが出来ます。
解説
-
JDK 6
以前のSwingWorker.java
から一部メソッド名が変更されているが、基本的な使用方法は同じ -
SwingWorker#execute()
メソッドで処理が開始され、SwingWorker#doInBackground()
メソッドがバックグラウンドのワーカースレッドで実行される -
EDT
で実行する必要のある処理(上記の例では処理中にJTextArea
へのメッセージの書き出し)はSwingWorker#process()
メソッドをオーバーライドしてSwingWorker#publish()
メソッドで呼び出したり、SwingWorker#firePropertyChange()
を使用する - プログレスバーの処理には
SwingWorker#setProgress(int)
が予め用意されているので、SwingWorker#addPropertyChangeListener(ProgressListener)
を設定するだけで使用可能 -
SwingWorker#setProgress(int)
で設定できるのは0
から100
で固定#spanend #spanadd protected final void setProgress(int progress) { #spanend if (progress < 0 || progress > 100) { throw new IllegalArgumentException("the value should be from 0 to 100"); } // ... #spanadd
- 実行中の処理のキャンセルは
SwingWorker#cancel(boolean)
メソッドで実行する- キャンセルされたかどうかは
SwingWorker#isCancelled()
メソッドで判定可能
- キャンセルされたかどうかは
- actionPerformed() is EDT?: true
- doInBackground() is EDT?: false
- process() is EDT?: true
- done() is EDT?: true
- -
- 現在のスレッドがイベントディスパッチスレッド(以下
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()
メソッド内で実行する
-
参考リンク
- Improve Application Performance With SwingWorker in Java SE 6
- Worker Threads and SwingWorker
- JTableのセルにJProgressBarを表示
- -
-
SwingWorker#process()
メソッド内などでJPanel#isDisplayable()
を呼び、アプリケーション(frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
が設定されている)が終了している場合は、タスクを中断することでSwingWorker
が生き残るのを防止
コメント
- 以前のSwingWorkerの使い方などは、Swing/AnimeIcon、
Swing/RecursiveFileSearchなどのソースコードやリンク先を参考にしてみてください。 -- terai
参考リンク
- SwingWorker (Java Platform SE 8)
- Improve Application Performance With SwingWorker in Java SE 6
- Worker Threads and SwingWorker
- JTableのセルにJProgressBarを表示
- SwingWorkerで複数のJProgressBarを使用する
- SwingWorkerの一時停止と再開