The JavaTM Tutorial
Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components

How to Monitor Progress

Sometimes a task running within a program might take a while to complete. A user-friendly program provides some indication to the user about how long the task might take and how much work has already been done. If you don't know or don't want to indicate how complete the task is, you can use a cursor or an animated image to indicate that some work is occurring. If, on the other hand, you want to convey how complete the task is, then 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. As of 1.4, you can show this uncertainty by putting the progress bar in indeterminate mode. In this mode, the progress bar displays animation to indicate that work is occurring. As soon as the program determines the length of the task, you should switch the progress bar back into its default, determinate mode. In the Java look and feel, indeterminate progress bars look like this:

An indeterminate progress bar

Swing provides three classes to help you use progress bars:

JProgressBar(in the API reference documentation)
A visible component to graphically display how much of a total task has completed. See How to Use Progress Bars for information and an example of using a progress bar.
ProgressMonitor(in the API reference documentation)
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(in the API reference documentation)
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 I/O: Reading and Writing (but no 'rithmetic)(in the Creating a GUI with JFC/Swing trail). You can get the stream's progress monitor with a call to getProgressMonitor and configure it as described in How to Use Progress Monitors.
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.

How to Use 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: 
  1. Compile and run the application. The main source file is ProgressBarDemo.java(in a .java source file). You will also need LongTask.java(in a .java source file) and SwingWorker.java(in a .java source file).
    See Getting Started with Swing if you need help compiling or running this application.

  2. Push the Start button. Watch the progress bar as the task makes progress. The task displays its output in the text area at the bottom of the window.

Below is the code from ProgressBarDemo.java(in a .java source file) that creates and sets up the progress bar:
//Where member variables are declared:
JProgressBar progressBar;
    //...in the constructor for the demo's frame:
    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. 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. 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.

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. By default, the progress bar displays the value returned by its getPercentComplete method formatted as a percent, such as 33%. Alternatively, you can replace the default with a different string by calling setString. For example,

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

You start this example's task by clicking the Start button. Once the task has begun, a timer (an instance of the Timer class) fires an action event every second. Here's the ActionPerformed method of the timer's action listener:

public void actionPerformed(ActionEvent evt) {
    progressBar.setValue(task.getCurrent());
    taskOutput.append(task.getMessage() + newline);
    taskOutput.setCaretPosition(taskOutput.getDocument().getLength());
    if (task.done()) {
	Toolkit.getDefaultToolkit().beep();
	timer.stop();
	startButton.setEnabled(true);
	progressBar.setValue(progressBar.getMinimum());
    }
}
The bold line of code gets the amount of work completed by the task and updates the progress bar with that value. So this example's progress bar measures the progress made by the task each second, not the elapsed time. The rest of the code appends a message to the output log (a text area named taskOutput) and, if the task is done, turns the timer off and resets the other controls.

As mentioned, the long-running task in this program runs in a separate thread. Generally, it's a good idea to isolate a potentially long-running task in its own thread so that the task doesn't block the rest of the program. The long-running task is implemented by LongTask.java(in a .java source file), which uses a SwingWorker to ensure that the thread runs safely. See Using the SwingWorker Class in Threads and Swing for information about the SwingWorker class.

[PENDING: We need to discuss and give an example that shows how to use indeterminate progress bars. At its most basic, you use pb.setIndeterminate(true) to make a progress indeterminate, and then pb.setIndeterminate(false) to set it back to its default state.]

How to Use Progress Monitors

Now let's rewrite the previous example to use a progress monitor instead of a progress bar. Here's a picture of the new demo program, ProgressMonitorDemo.java(in a .java source file):

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


Try this: 
  1. Compile and run the application. The main source file is ProgressMonitorDemo.java(in a .java source file). You will also need LongTask.java(in a .java source file) and SwingWorker.java(in a .java source file).
    See Getting Started with Swing if you need help compiling or running this application.
  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: After the example creates the progress monitor, it configures the monitor further:
progressMonitor.setProgress(0);
progressMonitor.setMillisToDecideToPopup(2 * ONE_SECOND);
The first line sets the current position of the progress bar on the dialog. The second tells the progress monitor to wait two seconds before deciding whether to bring up a dialog. If, after two seconds, the progress monitor's progress is less than its maximum, the monitor will bring up the dialog.

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.done()) {
    progressMonitor.close();
    task.stop();
    Toolkit.getDefaultToolkit().beep();
    timer.stop();
    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.

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.

The Progress Monitoring API

The following tables list the commonly used API for using progress bars and progress monitors. Because JProgressBar is a subclass of JComponent, other methods you are likely to call on a JProgressBar are listed in The JComponent Class. Note that ProgressMonitor is a subclass of Object and is not a visual component.

The API for monitoring progress falls into these categories:

Creating the Progress Bar
Constructor Purpose
JProgressBar()
JProgressBar(int, int)
Create a horizontal progress bar. The default constructor initializes the progress bar with a minimum and initial value of 0 and a maximum of 100. Use the min and max arguments to specify other values.
JProgressBar(int)
JProgressBar(int, int, int)
Create a progress bar with the specified orientation, which can be either JProgressBar.HORIZONTAL or JProgressBar.VERTICAL. The other 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 this method as an alternative to using the individual set/get methods listed above.

Controlling the Progress Bar's Appearance
Method Purpose
void setIndeterminate(boolean) By specifying true, put the progress bar into indeterminate mode. Specifying false puts the progress bar back into its default, determinate mode. Introduced in 1.4.
void setOrientation(int)
int getOrientation()
Set or get whether the progress bar is vertical or horizontal. Acceptable values are JProgressBar.VERTICAL or JProgressBar.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. You can set the string to be displayed with 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. The Object argument is a message to put on the option pane within the dialog. The value of this object is typically a String. The String argument is a changeable status note. The final two int arguments set the minimum and maximum values, respectively, for the progress bar used in the dialog.
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.
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 table shows the examples that use JProgressBar, ProgressMonitor, or ProgressMonitorInputStream, and where those examples are described.

Example Where Described Notes
ProgressBarDemo This section and How to Use Swing Timers 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.


Previous Page Lesson Contents Next Page Start of Tutorial > Start of Trail > Start of Lesson Search
Feedback Form

Copyright 1995-2002 Sun Microsystems, Inc. All rights reserved.