Merlin 的魔力: 不确定的进度条

Merlin 的魔力: 不确定的进度条

Merlin 的魔力: 不确定的进度条

JProgressBar 的一个细微但是重要的更新

级别: 初级
John Zukowski ([email protected]), 总裁, JZ Ventures, Inc
2003 年 12 月 01 日

开发人员用 JProgressBar 组件向用户显示一项任务的进度。针对非常长的任务或者难于精确确定完成进度的任务,Merlin版本对 JProgressBar 增加了一个不确定模式。本月,专栏作者 John Zukowski 对 JProgressBar 的使用作了重新介绍,并讨论了它的新的不确定模式。您可以在本文的 讨论论坛中与作者以及其他读者共享您的想法(您也可以单击文章顶部或者底部的 讨论进入论坛)。

在 Java 2 SDK, Standard Edition,版本 1.4 中,有了一些大的变化,如增加了像 JSpinner 这样的新组件、像 SpringLayout 这样的新布局管理器、或者像 Java Logging API 这样的新 API。而另一些变化则没有这么显著,如小的改进或者对现有 API 的优化。本月关于 SpringLayout 组件的技巧就属于后一种情况。它是细微的,但是很重要。

进度条的基本用法

JProgressBar 是原来的 Swing 组件集中的一个。它提供了一种以图形方式显示进程完成进度的简单方式。当进程进行时,一个长条就会在该组件上逐渐延伸,直到任务完成并且长条全部填满。长条的移动通常是某个多线程任务的一部分,这有助于避免阻塞应用程序其余部分的进度,如常规的屏幕更新。虽然没有哪一条特定的规则说进度条必须进行线性移动,但是如果看到进程从 10% 移动到 35%,然后又回到 27%,然后再增加到 80%,最后以 0% 结束,作为用户我会觉得多少有些古怪。

用五个构造函数中的一个来构造 JProgressBar ,如清单 1 所示:


清单 1. JProgressBar 构造函数
  public JProgressBar()
            public JProgressBar(int orientation)
            public JProgressBar(int minimum, int maximum)
            public JProgressBar(int orientation, int minimum, int maximum)
            public JProgressBar(BoundedRangeModel model)
            

JProgressBar 需要初始化方向和值范围。方向是通过 JProgressBarVERTICAL 或者 HORIZONTAL 常量确定的。默认为 HORIZONTAL

在创建了这个组件并在屏幕上显示它后,启动第二个线程以执行需要测量其进度的任务。然后定期用 setValue() 方法更新进度条的值以显示任务的当前进展。清单 2 显示了 setValue() 的一个简单例子:


清单 2. 简单的 JProgressBar 使用方法
import javax.swing.*;
            import java.awt.*;
            import java.awt.event.*;
            import java.lang.reflect.*;
            public class ProgressSample {
            static 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();
            Runnable runner = new Runnable() {
            public void run() {
            int value = progressBar.getValue();
            progressBar.setValue(value+1);
            }
            };
            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) {
            }
            }
            }
            }
            public static void main(String args[]) {
            // Initialize
            final JProgressBar aJProgressBar = new JProgressBar(0, 100);
            final JButton aJButton = new JButton("Start");
            ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            aJButton.setEnabled(false);
            Thread stepper = new BarThread(aJProgressBar);
            stepper.start();
            }
            };
            aJButton.addActionListener(actionListener);
            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.show();
            }
            }
            

第一次运行这段代码时,您会看到类似于图 1 的屏幕。


图 1. 开始屏幕

单击这个按钮,启动第二个任务,并在它运行时更新进度条。图 2 显示了运行到一半时的进度条。


图 2. 屏幕显示进度

这里没什么特别的。主要代码创建带有一个按钮和进度条的 GUI。当您选择按钮时,它就引发操作以更新进度条。进度条用来对某些任务进行测量。在示例程序中,这个任务就是休眠半秒 100 次。

在默认情况下,除了进度条外,没有其他关于进度的图形指示。添加如下的一行代码,您就可以在任务完成过程中,让进度条显示任务完成的百分比:

  aJProgressBar.setStringPainted(true);
            

图 3 显示了我们增加了新代码的屏幕:


图 3. 显示完成百分比





回页首


使用不确定模式

从 Merlin 版本开始, JProgressBar 还支持另一种模式 ―― 确定。对于非固定步数的长任务,可以使用这种模式。它显示固定的动画以表明有些事情正在发生,但是它不表明完成的百分比。如果您确定了任务所要花费的时间,就可以切换回确定模式。在不确定模式下, JProgressBar 显示一个长条,在显示区域中来回移动。

清单 3 显示了这种模式的一个例子。这个新方法就是 setIndeterminate() 。值为 true 意味着不确定,而值为 false 则意味着普通或者确定。


清单 3. 不确定进度条
import javax.swing.*;
            import java.awt.*;
            import java.awt.event.*;
            public class ProgressSample2 {
            public static void main(String args[]) {
            final JProgressBar aJProgressBar = new JProgressBar(0, 100);
            aJProgressBar.setIndeterminate(true);
            JButton aJButton = new JButton("Toggle");
            ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent e) {
            boolean indeterminate = aJProgressBar.isIndeterminate();
            aJProgressBar.setIndeterminate(!indeterminate);
            }
            };
            aJButton.addActionListener(actionListener);
            JFrame theFrame = new JFrame("Indeterminate");
            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.show();
            }
            }
            

图 4显示相关的屏幕(您需要想像这个长条是来回移动的)。按钮用于在进度条的不确定和确定模式之间进行切换。


图 4. 不确定模式

有两种新的 UI 默认值用于改变重绘时间间隔和循环时间: ProgressBar.repaintIntervalProgressBar.cycleTime 。改变这些设置 ―― 如下所示 ―― 会改变显示速度。循环时间必须是重绘时间间隔的偶数倍,所以如果间隔为 100,那么循环时间应该是 200、500 或者 1000 ―― 但不能是 750。

  UIManager.put("ProgressBar.repaintInterval", new Integer(150));
            UIManager.put("ProgressBar.cycleTime", new Integer(1050));
            

注意您需要在创建进度条 之前设置这些值。





结束语

ProgressBar 还有很多内容,但是其他特性在 1.4 版中都没有改变。我们简单回顾了这个组件的原有使用方式,并介绍了在 Merlin 版本中它的新特性。您也可以考虑用 ProgressMonitor 或者 ProgressMonitorInputStream 监视这些长任务的进度。它们都在内部利用了 JProgressBar 的优点。



原文:http://www.ibm.com/developerworks/cn/java/j-mer11183/index.html

你可能感兴趣的:(Merlin 的魔力: 不确定的进度条)