« canvas上にHTML要素を置く:JavaScriptメモ | トップページ | ◇トモイマシテ(と思いまして):日本語の拍の消失 »

Swingで時間のかかる処理の進捗表示:Javaメモ

m(_ _)mすいません。ちと怪しい

 JAVAのSwing表示で時間のかかる作業の進捗表示をする

時間のかかる作業をGUIから起動する場合、進捗状況が把握できなく不安になる ことがあります。

作業を別スレッドで行い、そのスレッドからGUIの要素に進捗表示を行い、 終了などのイベントをGUI部に送るサンプルを載せます。

// ProgressTest.java:別スレッドだてで進捗状況を画面に表示する
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
// メインのながなが作業(GUIとは別スレッドで動く)
class TestRunner extends Thread{
   ProgressTest win;   // 親方
   int          count;
   TestRunner(ProgressTest win_,int count_){
      win  = win_;
      count= count_;
      }
   public void run(){
      try{
         for(int n=count;n>=0;--n){
            // text系はswingの制御スレッド外から変更可能
            win.tf_status.setText(Integer.toString(n));// 親画面に直接設定
            Thread.sleep(1000);
            }
         // invokeLaterではthisは伝わらない
         win.actionPerformed(new ActionEvent(this,0,"カウントが終わりました"));
         }
      catch(Exception e){e.printStackTrace(System.err);}
      }
   }
// メインのウィンドウ
public class ProgressTest extends JFrame implements ActionListener{
   private JTextField tf_count;  // 開始カウント数の設定
   private JButton    btn_start; // 開始ボタン
   private JButton    btn_end;   // 終了ボタン
   public  JTextField tf_status; // 進捗(カウント)表示
   private TestRunner runner;
   public void actionPerformed(ActionEvent e){
      try{
         Object src= e.getSource();
         if( src==btn_start && runner==null ){   // 開始ボタンが押された
            int count = Integer.parseInt(tf_count.getText());
            runner = new TestRunner(this,count); // 作業者生成
            runner.start();                      // 作業開始
            }
         else if( src==btn_end ){ // 終了ボタンが押された
            System.exit(0);
            }
         else if( src==runner ){  // TestRunnerからのイベント
            JOptionPane.showMessageDialog(
                       this ,e.getActionCommand(), "確認" ,
			   JOptionPane.INFORMATION_MESSAGE);
            runner=null;
            }
         }
      catch(Exception ee){
         ee.printStackTrace(System.err);
         }
      }
   public static void main(String[] args) {
      ProgressTest win = new ProgressTest();
      win.pack();          // サイズを中身に合わせるおまじない
      win.setVisible(true);// 表示をするおまじない
      }
   public ProgressTest() {
      super("ProgressTest");
      Container pane = getContentPane();
      // 最外殻
      JPanel p0= new JPanel();
      p0.setLayout(new BoxLayout(p0,BoxLayout.Y_AXIS));
      pane.add(p0);
      // 1段目
      JPanel p1= new JPanel();
      p1.setLayout(new BoxLayout(p1,BoxLayout.X_AXIS));
      p0.add(p1);
      p1.add(new JLabel("開始カウント: "));
      tf_count = new JTextField("5");
      p1.add(tf_count);
      // 2段目
      JPanel p2= new JPanel();
      p2.setLayout(new BoxLayout(p2,BoxLayout.X_AXIS));
      p0.add(p2);
      btn_start = new JButton("カウント開始");
      btn_end   = new JButton("試験終了");
      btn_start.addActionListener(this);
      btn_end.addActionListener(this);
      p2.add(btn_start);
      p2.add(btn_end);
      // status行
      JPanel ps= new JPanel();
      ps.setLayout(new BoxLayout(ps,BoxLayout.X_AXIS));
      p0.add(ps);
      ps.add(new JLabel("カウント  : "));
      tf_status = new JTextField("");
      ps.add(tf_status);
      // ×で終了するおまじない
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      }
   }

表示画面は次のようになります。

プログラムではTestRunnerが時間のかかる処理を行っており スレッド化されています。

Threadの派生として作成し、run()関数に処理を記述します。

GUIとのやり取りのためProgressTestを変数として保持しています。
途中経過はGUIの要素に直接値をセットしています。GUIとは別スレッドですが、Textに 対する操作は問題なくGUIに反映されます(らしい)。

終了イベントをActionPerformed()呼び出しで通知しています。引数として作成する ActionEventに自分自身と、適当なコード、適当なメッセージを乗せます。
GUIの要素に直接値をセットせず、全てイベントで渡してGUI側でセットすることももちろん可能です。
SwingUtilities.invokeLater()を用いる場合、thisがうまく伝わりません。

GUI側はstart()でTestRunnerを起動し、ActionPerformedでTestRunnerからのイベントを待ちます。
ここでは単純にイベントからメッセージを取り出し表示しています。

ソースとantのbuild.xmlとant起動バッチを置きました。A10_test.batでビルドし起動します。
WinProgress.zip

|

« canvas上にHTML要素を置く:JavaScriptメモ | トップページ | ◇トモイマシテ(と思いまして):日本語の拍の消失 »

トラックバック


この記事へのトラックバック一覧です: Swingで時間のかかる処理の進捗表示:Javaメモ:

« canvas上にHTML要素を置く:JavaScriptメモ | トップページ | ◇トモイマシテ(と思いまして):日本語の拍の消失 »