Documentation

The Java™ Tutorials
Hide TOC
How to Use Progress Bars如何使用进度条
Trail: Creating a GUI With Swing
Lesson: Using Swing Components
Section: How to Use Various Components

How to Use Progress Bars如何使用进度条

Sometimes a task running within a program might take a while to complete. 有时,在程序中运行的任务可能需要一段时间才能完成。A user-friendly program provides some indication to the user that the task is occurring, how long the task might take, and how much work has already been done. 一个用户友好的程序向用户提供一些指示,说明任务正在发生,任务可能需要多长时间,以及已经完成了多少工作。One way of indicating work, and perhaps the amount of progress, is to use an animated image.指示工作的一种方式,可能是进度的数量,是使用动画图像。

Another way of indicating work is to set the wait cursor, using the Cursor class and the Component-defined setCursor method. 指示工作的另一种方法是使用Cursor类和Component定义的setCursor方法设置等待游标。For example, the following code makes the wait cursor be displayed when the cursor is over container (including any components it contains that have no cursor specified):例如,以下代码使当光标位于container上时显示等待光标(包括它包含的未指定光标的任何组件):

container.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

To convey how complete a task is, you can use a progress bar like this one:要传达任务的完成程度,可以使用如下进度条:

A typical progress bar

Sometimes you can't immediately determine the length of a long-running task, or the task might stay stuck at the same state of completion for a long time. 有时,您无法立即确定长时间运行的任务的长度,或者任务可能长时间停留在相同的完成状态。You can show work without measurable progress by putting the progress bar in indeterminate mode. 通过将进度条置于不确定模式,可以显示没有可测量进度的工作。A progress bar in indeterminate mode displays animation to indicate that work is occurring. 不确定模式下的进度条显示动画以指示正在进行工作。As soon as the progress bar can display more meaningful information, you should switch it back into its default, determinate mode. 一旦进度条能够显示更多有意义的信息,您就应该将其切换回默认的确定模式。In the Java look and feel, indeterminate progress bars look like this:在Java外观中,不确定进度条如下所示:

An indeterminate progress bar

Swing provides three classes to help you use progress bars:Swing提供了三个类来帮助您使用进度条:

JProgressBar
A visible component to graphically display how much of a total task has completed. 一个可视化组件,以图形方式显示总任务完成的程度。See Using Determinate Progress Bars for information and an example of using a typical progress bar. 有关信息和使用典型进度条的示例,请参阅使用确定进度条The section Using Indeterminate Mode tells you how to animate a progress bar to show activity before the task's scope is known.使用不确定模式部分告诉您如何设置进度条的动画,以便在任务范围已知之前显示活动。
ProgressMonitor
Not a visible component. 不是可见组件。Instead, an instance of this class monitors the progress of a task and pops up a dialog if necessary. 相反,此类的实例监视任务的进度,并在必要时弹出对话框See How to Use Progress Monitors for details and an example of using a progress monitor.有关详细信息和使用进度监视器的示例,请参阅如何使用进度监视器
ProgressMonitorInputStream
An input stream with an attached progress monitor, which monitors reading from the stream. 带有附加进度监视器的输入流,该监视器监视从流中读取的内容。You use an instance of this stream like any of the other input streams described in Basic I/O. 您可以像基本I/O中描述的任何其他输入流一样使用此流的实例。You can get the stream's progress monitor with a call to getProgressMonitor and configure it as described in How to Use Progress Monitors.您可以通过调用getProgressMonitor来获取流的进度监视器,并按照如何使用进度监视器中的描述进行配置。

After you see a progress bar and a progress monitor in action, Deciding Whether to Use a Progress Bar or a Progress Monitor can help you figure out which is appropriate for your application.在看到进度条和进度监视器运行后,决定使用进度条还是进度监视器可以帮助您找出适合您的应用程序的方法。

Using Determinate Progress Bars使用确定进度条

Here's a picture of a small demo application that uses a progress bar to measure the progress of a task that runs in its own thread:下面是一个小型演示应用程序的图片,它使用进度条来测量在自己线程中运行的任务的进度:

A snapshot of ProgressBarDemo, which uses a progress bar

Try this: 

The following code, from ProgressBarDemo.java, creates and sets up the progress bar:来自ProgressBarDemo.java的以下代码创建并设置进度条:

//Where member variables are declared:
JProgressBar progressBar;
...
//Where the GUI is constructed:
progressBar = new JProgressBar(0, task.getLengthOfTask());
progressBar.setValue(0);
progressBar.setStringPainted(true);

The constructor that creates the progress bar sets the progress bar's minimum and maximum values. 创建进度条的构造函数设置进度条的最小值和最大值。You can also set these values with setMinimum and setMaximum. 您还可以使用setMinimumsetMaximum设置这些值。The minimum and maximum values used in this program are 0 and the length of the task, which is typical of many programs and tasks. 该程序中使用的最小值和最大值为0和任务长度,这是许多程序和任务的典型值。However, a progress bar's minimum and maximum values can be any value, even negative. 但是,进度条的最小值和最大值可以是任何值,甚至是负值。The code snippet also sets the progress bar's current value to 0.代码段还将进度条的当前值设置为0。

The call to setStringPainted causes the progress bar to display, within its bounds, a textual indication of the percentage of the task that has completed. 调用setStringPainted会导致进度条在其边界内显示已完成任务百分比的文本指示。By default, the progress bar displays the value returned by its getPercentComplete method formatted as a percent, such as 33%. 默认情况下,进度条显示其getPercentComplete方法返回的值,格式为百分比,例如33%Alternatively, you can replace the default with a different string by calling setString. 或者,您可以通过调用setString将默认值替换为其他字符串。For example,例如

if (/*...half way done...*/)
    progressBar.setString("Half way there!");

When the user clicks Start, an instance of the inner class Task is created and executed.当用户单击开始时,将创建并执行内部类任务的实例。

public void actionPerformed(ActionEvent evt) {
    startButton.setEnabled(false);
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    done = false;
task = new Task();
    task.addPropertyChangeListener(this);
    task.execute();
}

Task is a subclass of javax.swing.SwingWorker. javax.swing.SwingWorker的子类。The Task instance does three important things for ProgressBarDemo:Task实例为ProgressBarDemo做了三件重要的事情:

  1. The instance invokes the doInBackground in a separate thread. 该实例在单独的线程中调用doInBackgroundThis is where the long-running task is actually executed. 这是实际执行长时间运行任务的地方。Using a background thread instead of the event-dispatching thread prevents the user interface from freezing while the task is running.使用后台线程而不是事件调度线程可以防止用户界面在任务运行时冻结。
  2. When the background task is complete, the instance invokes the done method in the event-dispatching thread.后台任务完成后,实例调用事件调度线程中的done方法。
  3. The instance maintains a bound property, progress, that is updated to indicate the progress of the task. 实例维护一个绑定属性progress,该属性被更新以指示任务的进度。The propertyChange method is invoked each time progress changes.每次progress更改时都会调用propertyChange方法。

See Worker Threads and SwingWorker in Concurrency in Swing for more information about SwingWorker.有关SwingWorker的更多信息,请参阅Swing中的并发中的工作线程和SwingWorker

The background task in ProgressBarDemo simulates a real task by reporting random amounts of progress at random intervals. ProgressBarDemo中的后台任务通过以随机间隔报告随机进度来模拟真实任务。The propertyChange method responds to changes in the task's progress property by updating the progress bar:propertyChange方法通过更新进度栏来响应任务progress属性的更改:

public void propertyChange(PropertyChangeEvent evt) {
    if (!done) {
        int progress = task.getProgress();
progressBar.setValue(progress);
        taskOutput.append(String.format(
                "Completed %d%% of task.\n", progress));
    }

When the background task is complete, the task's done method resets the progress bar:后台任务完成后,任务的完成方法将重置进度条:

public void done() {
    //Tell progress listener to stop updating progress bar.
    done = true;
    Toolkit.getDefaultToolkit().beep();
    startButton.setEnabled(true);
    setCursor(null); //turn off the wait cursor
progressBar.setValue(progressBar.getMinimum());
    taskOutput.append("Done!\n");
}

Note that the done method sets the done field to true, preventing propertyChange from making further updates to the progress bar. 请注意,done方法将done字段设置为true,从而防止propertyChange对进度条进行进一步更新。This is necessary because the final updates to the progress property may occur after done is invoked.这是必要的,因为对progress属性的最终更新可能在调用done之后发生。

Using Indeterminate Mode使用不确定模式

In ProgressBarDemo2 indeterminate mode is set until actual progress begins:ProgressBarDemo2中,设置不确定模式,直到实际进度开始:

public void propertyChange(PropertyChangeEvent evt) {
    if (!done) {
        int progress = task.getProgress();
        if (progress == 0) {
progressBar.setIndeterminate(true);
            taskOutput.append("No progress yet\n");
        } else {
progressBar.setIndeterminate(false);
            progressBar.setString(null);
            progressBar.setValue(progress);
            taskOutput.append(String.format(
                    "Completed %d%% of task.\n", progress));
        }
    }
}

The other changes in the code are related to string display. 代码中的其他更改与字符串显示有关。A progress bar that displays a string is likely to be taller than one that doesn't, and, as the demo designers, we've arbitrarily decided that this progress bar should display a string only when it's in the default, determinate mode. 显示字符串的进度条可能比不显示的进度条高,而且,作为演示设计师,我们任意决定该进度条仅在默认的确定模式下显示字符串。However, we want to avoid the layout ugliness that might result if the progress bar changed height when it changed modes. 然而,我们希望避免当进度条改变模式时改变高度可能导致的布局丑陋。Thus, the code leaves in the call to setStringPainted(true) but adds a call to setString("") so that no text will be displayed. 因此,代码保留了对setStringPainted(true)的调用,但添加了对setString("")的调用,因此不会显示任何文本。Later, when the progress bar switches from indeterminate to determinate mode, invoking setString(null) makes the progress bar display its default string.稍后,当进度条从不确定模式切换到确定模式时,调用setString(null)将使进度条显示其默认字符串。

One change we did not make was removing the call to progressBar.setValue from the progress event handler. 我们没有做的一个更改是从progress事件处理程序中删除对progressBar.setValue的调用。The call doesn't do any harm because an indeterminate progress bar doesn't use its value property, except perhaps to display it in the status string. 调用不会造成任何伤害,因为不确定的进度条不使用其值属性,除非可能在状态字符串中显示它。In fact, keeping the progress bar's data as up-to-date as possible is a good practice, since some look and feels might not support indeterminate mode.事实上,保持进度条的数据尽可能最新是一个很好的做法,因为有些外观可能不支持不确定模式。


Try this: 
  1. Click the Launch button to run the ProgressBar2 Demo using Java™ Web Start (download JDK 7 or later). 单击启动按钮,使用Java™Web启动运行ProgressBar2演示(下载JDK 7或更高版本)。Alternatively, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引Launches the ProgressBar2 Demo example
  2. Push the Start button. 按下启动按钮。Note that the progress bar starts animating as soon as the button is pressed, and then switches back into determinate mode (like ProgressBarDemo).请注意,只要按下按钮,进度条就会开始动画,然后切换回确定模式(如ProgressBarDemo)。

How to Use Progress Monitors如何使用进度监视器

Now let's rewrite ProgressBarDemo to use a progress monitor instead of a progress bar. 现在,让我们重写ProgressBarDemo以使用进度监视器而不是进度条。Here's a picture of the new demo program, ProgressMonitorDemo:以下是新演示程序ProgressMonitorDemo的图片:

A snapshot of ProgressMonitorDemo and a dialog brought up by a progress monitor

Try this: 
  1. Click the Launch button to run the ProgressMonitor Demo using Java™ Web Start (download JDK 7 or later). 单击启动按钮,使用Java™Web启动运行ProgressMonitor演示(下载JDK 7或更高版本)。Alternatively, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引Launches the ProgressMonitor Demo example
  2. Push the Start button. 按下启动按钮。After a certain amount of time, the program displays a progress dialog.经过一定时间后,程序将显示进度对话框。
  3. Click the OK button. 单击确定按钮。Note that the task continues even though the dialog is gone.请注意,即使对话框消失,任务仍将继续。
  4. Start another task. 开始另一项任务。After the dialog pops up, click the Cancel button. 对话框弹出后,单击取消按钮。The dialog goes away and the task stops.对话框消失,任务停止。

A progress monitor cannot be used again, so a new one must be created each time a new task is started. 无法再次使用进度监视器,因此每次启动新任务时都必须创建一个新的进度监视器。This program creates a progress monitor each time the user starts a new task with the Start button.每次用户使用“开始”按钮启动新任务时,该程序都会创建一个进度监视器。

Here's the statement that creates the progress monitor:下面是创建进度监视器的语句:

progressMonitor = new ProgressMonitor(ProgressMonitorDemo.this,
                                      "Running a Long Task",
                                      "", 0, task.getLengthOfTask());

This code uses ProgressMonitor's only constructor to create the monitor and initialize several arguments:此代码使用ProgressMonitor的唯一构造函数创建监视器并初始化几个参数:

By default, a progress monitor waits a minimum of 500 milliseconds before deciding whether to pop up the dialog. 默认情况下,进度监视器在决定是否弹出对话框之前至少等待500毫秒。It also waits for the progress to become more than the minimum value. 它还等待进度超过最小值。If it calculates that the task will take more than 2000 milliseconds to complete, the progress dialog appears. 如果计算出任务完成时间超过2000毫秒,则会显示“进度”对话框。To adjust the minimum waiting period, invoke setMillisToDecidedToPopup. 要调整最小等待时间,请调用setMillistodedTopopupTo adjust the minimum progress time required for a dialog to appear, invoke setMillisToPopup.要调整对话框显示所需的最小进度时间,请调用setMillistopup

By the simple fact that this example uses a progress monitor, it adds a feature that wasn't present in the version of the program that uses a progress bar: The user can cancel the task by clicking the Cancel button on the dialog. 由于本示例使用进度监视器这一简单事实,它添加了一个在使用进度条的程序版本中不存在的功能:用户可以通过单击对话框上的“取消”按钮取消任务。Here's the code in the example that checks to see if the user canceled the task or if the task exited normally:下面是示例中检查用户是否取消任务或任务是否正常退出的代码:

if (progressMonitor.isCanceled() || task.isDone()) {
    progressMonitor.close();
    Toolkit.getDefaultToolkit().beep();
    if (progressMonitor.isCanceled()) {
        task.cancel(true);
        taskOutput.append("Task canceled.\n");
    } else {
        taskOutput.append("Task completed.\n");
    }
    startButton.setEnabled(true);
}

Note that the progress monitor doesn't itself cancel the task. 请注意,进度监视器本身不会取消任务。It provides the GUI and API to allow the program to do so easily.它提供了GUI和API,以允许程序轻松地执行此操作。

Deciding Whether to Use a Progress Bar or a Progress Monitor决定是否使用进度条或进度监视器

Use a progress bar if:在以下情况下使用进度条

Use a progress monitor if:在以下情况下使用进度监视器

If you decide to use a progress monitor and the task you are monitoring is reading from an input stream, use the ProgressMonitorInputStream class.如果您决定使用进度监视器,并且正在监视的任务正在从输入流读取,请使用ProgressMonitorInputStream类。

The Progress Monitoring API进度监控API

The following tables list the commonly used API for using progress bars and progress monitors. 下表列出了使用进度条和进度监视器的常用API。Because JProgressBar is a subclass of JComponent, other methods you are likely to call on a JProgressBar are listed in The JComponent Class. 因为JProgressBarJComponent的子类,所以您可能在JProgresBar上调用的其他方法都列在JComponnt中。Note that ProgressMonitor is a subclass of Object and is not a visual component.请注意,ProgressMonitorObject的子类,不是可视化组件。

The API for monitoring progress falls into these categories:用于监控进度的API分为以下几类:

Creating the Progress Bar创建进度条
Constructor构造函数 Purpose目的
JProgressBar()
JProgressBar(int, int)
Create a horizontal progress bar. 创建水平进度条。The no-argument constructor initializes the progress bar with a minimum and initial value of 0 and a maximum of 100. 无参数构造函数使用最小和初始值0和最大值100初始化进度条。The constructor with two integer arguments specifies the minimum and maximum values.具有两个整数参数的构造函数指定最小值和最大值。
JProgressBar(int)
JProgressBar(int, int, int)
Create a progress bar with the specified orientation, which can be either JProgressBar.HORIZONTAL or JProgressBar.VERTICAL. 创建具有指定方向的进度条,该方向可以是JProgressBar.HORIZONTALJProgressBar.VERTICALThe optional second and third arguments specify minimum and maximum values.可选的第二个和第三个参数指定最小值和最大值。
JProgressBar(BoundedRangeModel) Create a horizontal progress bar with the specified range model.使用指定的范围模型创建水平进度条。
Setting or Getting the Progress Bar's Constraints/Values设置或获取进度条的约束/值
Method方法 Purpose目的
void setValue(int)
int getValue()
Set or get the current value of the progress bar. 设置或获取进度条的当前值。The value is constrained by the minimum and maximum values.该值受最小值和最大值的约束。
double getPercentComplete() Get the percent complete for the progress bar.获取进度条的完成百分比。
void setMinimum(int)
int getMinimum()
Set or get the minimum value of the progress bar.设置或获取进度条的最小值。
void setMaximum(int)
int getMaximum()
Set or get the maximum value of the progress bar.设置或获取进度条的最大值。
void setModel(BoundedRangeModel)
BoundedRangeModel getModel()
Set or get the model used by the progress bar. 设置或获取进度条使用的模型。The model establishes the progress bar's constraints and values, so you can use it directly as an alternative to using the individual set/get methods listed above.该模型建立了进度条的约束和值,因此您可以直接使用它来替代使用上面列出的单独的set/get方法。
Controlling the Progress Bar's Appearance控制进度条的外观
Method方法 Purpose目的
void setIndeterminate(boolean) By specifying true, put the progress bar into indeterminate mode. 通过指定true,将进度条置于不确定模式。Specifying false puts the progress bar back into its default, determinate mode.指定false会将进度条返回到默认的确定模式。
void setOrientation(int)
int getOrientation()
Set or get whether the progress bar is vertical or horizontal. 设置或获取进度条是垂直还是水平。Acceptable values are JProgressBar.VERTICAL or JProgressBar.HORIZONTAL.可接受的值为JProgressBar.VERTICALJProgressBar.HORIZONTAL
void setBorderPainted(boolean)
boolean isBorderPainted()
Set or get whether the progress bar has a border.设置或获取进度条是否有边框。
void setStringPainted(boolean)
boolean isStringPainted()
Set or get whether the progress bar displays a percent string. 设置或获取进度条是否显示百分比字符串。By default, the value of the percent string is the value returned by getPercentComplete formatted as a percent. 默认情况下,百分比字符串的值是格式为百分比的getPercentComplete返回的值。You can set the string to be displayed with setString.您可以使用setString设置要显示的字符串。
void setString(String)
String getString()
Set or get the percent string.设置或获取百分比字符串。
Creating the Progress Monitor创建进度监视器
Method or Constructor方法或构造函数 Purpose目的
ProgressMonitor(Component, Object, String, int, int) Create a progress monitor. 创建进度监视器。The Component argument is the parent for the monitor's dialog. Component参数是监视器对话框的父项。The Object argument is a message to put on the option pane within the dialog. Object参数是要放在对话框的选项窗格上的消息。The value of this object is typically a String. 此对象的值通常是StringThe String argument is a changeable status note. String参数是一个可更改的状态注释。The final two int arguments set the minimum and maximum values, respectively, for the progress bar used in the dialog.最后两个int参数分别设置对话框中使用的进度条的最小值和最大值。
ProgressMonitor getProgressMonitor()
(in ProgressMonitorInputStream)
Gets a progress monitor that monitors reading from an input stream.获取监视从输入流读取的进度监视器。
Configuring the Progress Monitor配置进度监视器
Method方法 Purpose目的
void setMinimum(int)
int getMinimum()
Set or get the minimum value of the progress monitor. 设置或获取进度监视器的最小值。This value is used by the monitor to set up the progress bar in the dialog.监视器使用此值设置对话框中的进度条。
void setMaximum(int)
int getMaximum()
Set or get the maximum value of the progress monitor. 设置或获取进度监视器的最大值。This value is used by the monitor to set up the progress bar in the dialog.监视器使用此值设置对话框中的进度条。
void setProgress(int) Update the monitor's progress.更新监视器的进度。
void setNote(String)
String getNote()
Set or get the status note. 设置或获取状态注释。This note is displayed on the dialog. 此注释显示在对话框上。To omit the status note from the dialog, provide null as the third argument to the monitor's constructor.要从对话框中省略状态注释,请将null作为监视器构造函数的第三个参数。
void setMillisToDecideToPopup(int)
int getMillisToDecideToPopup()
Set or get the time after which the monitor should decide whether to popup a dialog.设置或获取监视器决定是否弹出对话框的时间。
Terminating the Progress Monitor终止进度监视器
Method方法 Purpose目的
void close() Close the progress monitor. 关闭进度监视器。This disposes of the dialog.这将处理该对话框。
boolean isCanceled() Determine whether the user pressed the Cancel button.确定用户是否按下了取消按钮。

Examples that Monitor Progress监控进度的示例

This following examples use JProgressBar or ProgressMonitor.以下示例使用JProgressBarProgressMonitor

Example示例 Where Described描述位置 Notes备注
ProgressBarDemo This section本节 Uses a basic progress bar to show progress on a task running in a separate thread.使用基本进度条显示在单独线程中运行的任务的进度。
ProgressBarDemo2 This section本节 Uses a basic progress bar to show progress on a task running in a separate thread.使用基本进度条显示在单独线程中运行的任务的进度。
ProgressMonitorDemo This section本节 Modification of the previous example that uses a progress monitor instead of a progress bar.对上一个示例的修改,该示例使用进度监视器而不是进度条。

If you are programming in JavaFX, see Progress Bar and Progress Indicator.如果您使用JavaFX编程,请参阅进度条和进度指示器


Previous page: How to Use Password Fields
Next page: How to Use Root Panes