« ビルダーの起動 | トップページ | ビルド処理の進捗状況表示 »

2004.04.08

進捗状況のダイアログ表示

処理の進捗状況を表示するためによく使用されるプログレスバー。ビルド作業やリファクタリングなど,比較的長い時間かかる処理を実行する際には,あとどれくらいで処理が終わるのか,または少なくとも長い時間がかかる処理をやってるよ,という表示をユーザに対してするべきである。ここでは,処理の進捗状況をダイアログを用いて表示するための手順を紹介する。

Eclipseでは,進捗状況を簡単に表示するためのクラスを提供してくれている。進捗状況をダイアログで簡単に表示したときは,ProgressMonitorDialogクラスを使用する

  Shell parent = ...;
  ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
  try {
    dialog.run(true, true, new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor)
          throws InvocationTargetException, InterruptedException {
        // 進捗を監視する処理
      }
    } );
  } catch(InvocationTargetException e) {
    // 処理中に何らかの例外が発生したときの処理
  } catch(InterruptedException e) {
    // キャンセルされたときの処理
  }

まず,ダイアログを表示するときの親となるShellオブジェクトを取得する(「Shellオブジェクトの取得」「Shellオブジェクトの取得 Part2」参照)。そしてProgressMonitorDialogオブジェクトをShellオブジェクトを元に生成する。

そして,ProgressMonitorDialogオブジェクトのrunメソッドを呼び出して,処理を開始する。runメソッドの引数は3つある。

  第1引数 - 別スレッドとして(3)の処理を実行するかどうか
  第2引数 - 処理の取り消しを有効とするかどうか
  第3引数 - 実行したい処理をカプセル化したオブジェクト

第1引数は通常はtrueでよい。もしfalseにした場合は,上記のコードを実行しているスレッドにより処理が行われてしまうため,[Cancel]ボタンが効かなくなったり,ダイアログの再描画が行われなくなるなどの好ましくない現象が生じてしまう。第2引数をfalseにすると,ダイアログ上にある[Cancel]ボタンがdisableになり,処理のキャンセルができなくなる。

第3引数には,進捗監視対象となる処理を持つオブジェクトを指定する。進捗監視対象の処理は,IRunnableWithProgressインタフェースの実装クラスとして作成するIRunnableWithProgressインタフェースの実装クラスにおいてrunメソッドを実装する。runメソッドは引数としてIProgressMonitorオブジェクトを持っている。runメソッド内において,処理の開始,経過および終了の各タイミングで,IProgressMonitorインタフェースに規定されたメソッドを呼び出すことにより,進捗状況がダイアログに表示される。タスク名,サブタスク名は,ダイアログに表示される。

  処理(タスク)開始時 - monitor.beginTask("タスク名", 合計仕事量)
  副処理(サブタスク)開始時 - monitor.subTask("サブタスク名")
  単位仕事完了時 - monitor.worked(完了仕事量)
  処理完了時 - monitor.done()

さらに,任意のタイミング(例えばサブタスクの開始直前など)でIProgressMonitorインタフェースのisCanceledメソッドを呼び出して,ユーザによって[Cancel]ボタンが押されたかどうかを検査し,処理をキャンセルすべきかどうかを見る必要がある。もしisCacneledメソッド呼び出しの結果がtrueだった場合は,InterruptedException例外をスローして処理がキャンセルされたことを通知する。この例外はProgressMonitorDialogクラスのrunメソッドからスローされてくるので,それをキャッチしてキャンセル処理を行う。

例えば,ある仕事(ここでは1秒寝るだけ)を10回繰り返す処理は,以下のような感じのコードになる。同時に,実行中のスナップショットも紹介しておこう。

  dialog.run(true, true, new IRunnableWithProgress() {
    public void run(IProgressMonitor monitor)
        throws InvocationTargetException, InterruptedException {
      monitor.beginTask("1秒寝る処理を10回繰り返します。", 10);
      for (int i = 0; i < 10; i++) {
        if (monitor.isCanceled()) {
          throw new InterruptedException("Cancel has been requested.");
        } else {
          monitor.subTask((i + 1) + "回目");
          Thread.sleep(1000);
          monitor.worked(1);
        }
      }
      monitor.done();
    }
  } );

ProgressMonitorDialog.gif

処理中に何らかの例外が発生した場合は,InvocationTargetException例外に発生した例外オブジェクトを持たせてスローする。そして,ProgressMonitorDialogクラスの使用元でInvocationTargetException例外をキャッチして適切な処理を行う。発生した例外は,getCauseメソッドで取得することができる

  try {
    dialog.run(true, true, new IRunnableWithProgress() {
      public void run(IProgressMonitor monitor)
          throws InvocationTargetException, InterruptedException {
        try {
          // 何らかの処理
        } catch(FileNotFoundException e) {
          throw new InvocationTargetException(e);
        }
      }
    } );
  } catch(InvocationTargetException e) {
    Throwable cause = e.getCause();
    if (cause instanceof FileNotFoundException) {
      // ファイルがなかったときの処理
    }
  }

このように,進捗状況の表示はProgressMonitorDialogクラスで簡単に実現できる。ユーザフレンドリーなGUIの構築には,このProgressMonitorDialogクラスは欠かすことのできないものである。

|

« ビルダーの起動 | トップページ | ビルド処理の進捗状況表示 »

コメント

InvocationTargetException例外から原因となった例外オブジェクトを取得する方法は,本文中のgetCauseメソッドのほかに,getTargetExceptionメソッドを使っても取得することができます(2つのメソッドは全く一緒の動作です)。

投稿: よういちろう | 2004.04.08 01:00 午後

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/12631/412219

この記事へのトラックバック一覧です: 進捗状況のダイアログ表示:

« ビルダーの起動 | トップページ | ビルド処理の進捗状況表示 »