■
プログレスバーの類い(プログレスダイアログでも何でもいいんだけど、とにかくある動作の進行状況を通知する機能)って、どうやって実現するんだっけ?
プログラミング言語とそのフレームワークごとに違うはずで、ここでは、JavaとSwingについて。ちょっと調べてみればすぐわかるし、本(Swing Tipsなど)を見れば一発なんだけど、課題としてあげておく。
とくに、メインフレーム(あるいはダイアログ)内に埋め込まれたウィジェットでそれを表現するには、どうしたらいいんだっけ?
以下は、課題のサンプルプログラム。結構めんどくさい。DeveloperWorksの「Merlinの魔術: 不確定プログレス・バー」によるプログレスバーのサンプル。(ちょっと変更、inner class, anonymous classなどをやめた。)
まず、プログレスバーを動かすスレッド。動かすプログレスバーをコンストラクタでもらっている。
class ProgressRunner implements Runnable { private JProgressBar progressBar; ProgressRunner(JProgressBar pbar) { progressBar = pbar; } public void run() { int value = progressBar.getValue(); progressBar.setValue(value+1); } }
次は、プログレスバーで進行状況を表示したいタスクスレッド。実際には、500ms待ちながらカウンターを増やしていって、カウンターが最大値になったら、スレッドは、終了する。プログレスバーを動かすスレッドをあらかじめ用意しておき、run()内で、カウンターを増やすたびに、プログレスバーを動かすスレッドを引数に指定して、SwingUtilities.invokeAndWait()を呼ぶところがミソらしい。そのために、コンストラクタでプログレスバーをこのクラスの利用側からもらっている。
class BarThread extends Thread { private static int DELAY = 500; JProgressBar progressBar; public BarThread(JProgressBar bar) { progressBar = bar; } public void run() { int minimum = progressBar.getMinimum(); int maximum = progressBar.getMaximum(); ProgressRunner runner = new ProgressRunner(progressBar); for (int i=minimum; i<maximum; i++) { try { SwingUtilities.invokeAndWait(runner); // Our task for each step is to just sleep Thread.sleep(DELAY); } catch (InterruptedException ignoredException) { } catch (InvocationTargetException ignoredException) { } } } }
あとは、タスクスレッドを開始するボタンのActionListenerとGUI本体。
ボタンが押されたら、ボタンをdisableにして、タスクスレッドを作って、開始する。
GUI本体は、プログレスバーとボタンを作って、JFrameに配置している。
class ButtonActionListener implements ActionListener { private JButton aJButton; private JProgressBar aJProgressBar; ButtonActionListener(JButton btn, JProgressBar pbar) { aJButton = btn; aJProgressBar = pbar; } public void actionPerformed(ActionEvent e) { aJButton.setEnabled(false); Thread stepper = new BarThread(aJProgressBar); stepper.start(); } } public class ProgressSample { public static void main(String args[]) { // Initialize final JProgressBar aJProgressBar = new JProgressBar(0, 100); final JButton aJButton = new JButton("Start"); aJButton.addActionListener(new ButtonActionListener(aJButton, aJProgressBar)); JFrame theFrame = new JFrame("Progress Bars"); theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container contentPane = theFrame.getContentPane(); contentPane.add(aJProgressBar, BorderLayout.NORTH); contentPane.add(aJButton, BorderLayout.SOUTH); theFrame.setSize(300, 100); theFrame.setVisible(true); } }