---
category: swing
folder: PauseResumeSwingWorker
title: SwingWorkerの一時停止と再開
tags: [SwingWorker, JProgressBar, JTextArea]
author: aterai
pubdate: 2011-07-25T14:41:32+09:00
description: SwingWorkerで処理の一時停止と再開を行います。
image: https://lh6.googleusercontent.com/-3BCjKLnQbGM/Ti0AQV5nkwI/AAAAAAAAA_s/RY75ol3pFak/s800/PauseResumeSwingWorker.png
hreflang:
    href: https://java-swing-tips.blogspot.com/2011/07/pause-and-resume-swingworker.html
    lang: en
---
* 概要 [#summary]
`SwingWorker`で処理の一時停止と再開を行います。

#download(https://lh6.googleusercontent.com/-3BCjKLnQbGM/Ti0AQV5nkwI/AAAAAAAAA_s/RY75ol3pFak/s800/PauseResumeSwingWorker.png)

* サンプルコード [#sourcecode]
#code(link){{
class RunAction extends AbstractAction {
  public RunAction() {
    super("run");
  }
  @Override public void actionPerformed(ActionEvent evt) {
    JProgressBar bar1 = new JProgressBar(0, 100);
    JProgressBar bar2 = new JProgressBar(0, 100);
    runButton.setEnabled(false);
    canButton.setEnabled(true);
    pauseButton.setEnabled(true);
    statusPanel.removeAll();
    statusPanel.add(bar1, BorderLayout.NORTH);
    statusPanel.add(bar2, BorderLayout.SOUTH);
    statusPanel.revalidate();
    worker = new SwingWorker<String, Progress>() {
      private final Random r = new Random();
      @Override public String doInBackground() {
        int current = 0;
        int lengthOfTask = 12; //filelist.size();
        publish(new Progress(Component.LOG, "Length Of Task: " + lengthOfTask));
        publish(new Progress(Component.LOG, "\n---------------------------\n"));
        while (current < lengthOfTask && !isCancelled()) {
          publish(new Progress(Component.LOG, "*"));
          if (!bar1.isDisplayable()) {
            return "Disposed";
          }
          try {
            convertFileToSomething();
          } catch (InterruptedException ie) {
            return "Interrupted";
          }
          publish(new Progress(Component.TOTAL, 100 * current / lengthOfTask));
          current++;
        }
        publish(new Progress(Component.LOG, "\n"));
        return "Done";
      }

      private void convertFileToSomething() throws InterruptedException {
        boolean flag = false;
        int current = 0;
        int lengthOfTask = 10 + r.nextInt(50);
        while (current <= lengthOfTask && !isCancelled()) {
          if (isPaused) {
            try {
              Thread.sleep(500);
            } catch (InterruptedException ie) {
              return;
            }
            publish(new Progress(Component.PAUSE, flag));
            flag ^= true;
            continue;
          }
          int iv = 100 * current / lengthOfTask;
          Thread.sleep(20); // dummy
          publish(new Progress(Component.FILE, iv + 1));
          current++;
        }
      }

      @Override protected void process(java.util.List<Progress> chunks) {
        for (Progress s: chunks) {
          switch (s.component) {
            case TOTAL: bar1.setValue((Integer) s.value); break;
            case FILE:  bar2.setValue((Integer) s.value); break;
            case LOG:   area.append((String) s.value); break;
            case PAUSE: {
              if ((Boolean) s.value) {
                area.append("*");
              } else {
                try {
                  Document doc = area.getDocument();
                  doc.remove(doc.getLength() - 1, 1);
                } catch (Exception ex) {
                  ex.printStackTrace();
                }
              }
              break;
            }
          }
        }
      }

      @Override public void done() {
        // ...
      }
    };
    worker.execute();
  }
}
// ...
private boolean isPaused = false;
class PauseAction extends AbstractAction {
  public PauseAction() {
    super("pause");
  }
  @Override public void actionPerformed(ActionEvent evt) {
    isPaused = (worker != null && !worker.isCancelled() && !isPaused);
    JButton b = (JButton) evt.getSource();
    b.setText(isPaused ? "resume" : "pause");
  }
}
}}

* 解説 [#explanation]
上記のサンプルでは、`SwingWorker#doInBackground()`内のループで一時停止のフラグを参照し、一時停止状態の場合は本来の処理(上記のサンプルではカウントアップするだけ)を行わずに、`Thread.sleep(...)`と停止中を表現するコンポーネントの更新(`JTextArea`の文字列を点滅)のみ繰り返す`SwingWorker`を使用しています。

* 参考リンク [#reference]
- [[SwingWorkerを使った処理の中断と進捗状況表示>Swing/SwingWorker]]
- [[SwingWorkerで複数のJProgressBarを使用する>Swing/TwoProgressBars]]

* コメント [#comment]
#comment
#comment