Using the JFC/Swing Packages |
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.The Swing package provides three classes to help you create GUIs that monitor and display the progress of a long-running task:
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.
JProgressBar
- A progress bar graphically displays how much of the total task has completed. See How to Use Progress Bars for information and an example of using a progress bar.
ProgressMonitor
- An instance of this class monitors the progress of a task. If the elapsed time of the task exceeds a program-specified value, the monitor pops up a dialog with a task description, a status note, a progress bar, an Ok button, and a Cancel button. 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 Reading and Writing. You can get the stream's progress monitor with a call to
getProgressMonitor
and configure it as described in How to Use Progress Monitors.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:Below is the code from
Try this:
- Compile and run the application. The main source file is
ProgressBarDemo.java
. You will also needLongTask.java
andSwingWorker.java
.
See Getting Started with Swing if you need help.- 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.
ProgressBarDemo.java
that creates and sets up the progress bar:The constructor used to create the progress bar sets the progress bar's minimum and maximum values. You can also set these values with...where member variables are delcared... JProgressBar progressBar; ... ...in the constructor for the demo's frame... progressBar = new JProgressBar(0, task.getLengthOfTask()); progressBar.setValue(0); progressBar.setStringPainted(true);setMinimum
andsetMaximum
. 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 minimum, current, and maximum values must be related as follows:If you attempt to set any of the values and the new value violates the relationship, the progress bar adjusts one or more of other values according to the rules established byminimum <= current <= maximumBoundedRangeModel
to maintain the relationship.The call to
setStringPainted
causes the progress bar display a percent string within its bounds. By default, the percent string indicates the percentage complete for the progress bar. The percent string is the value returned by thegetPercentComplete
method formatted as a percent. [PENDING: i've gone round and round on the wording of the previous two sentences. Kathy: can you make it better?] Alternatively, you can display a different string withsetString
.You start the 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 theActionPerformed
method of the timer's action listener:The bold line of code gets the amount of work completed by the task and updates the progress bar with that value. So the progress bar measures the progress made by the task each second, not the elapsed time. The rest of the code updates the output log, and if the task is done, turns the timer off, and resets the other controls.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()); } }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
, which uses aSwingWorker
to ensure that the thread runs safely within a Swing program. See Using the SwingWorker Class in Threads and Swing for information about theSwingWorker
class.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
: The general operation of this program is similar to the previous. You click the Start button to start the same long task used in the previous program. The task displays output in the text area at the bottom of the main window. However, this program uses a progress monitor instead of a progress bar.The previous example created the progress bar on startup. In contrast, this program creates the progress monitor in the Start button's action listener's
actionPerformed
method. A progress monitor cannot be used again, so a new one must be created each time a new task is started.Here's the statement to create the progress monitor:
The constructor used in this example initializes several progress monitor parameters.progressMonitor = new ProgressMonitor(ProgressMonitorDemo.this, "Running a Long Task", "", 0, task.getLengthOfTask());After the example creates the progress monitor, it configures the monitor further:
- The first argument provides the parent component to the dialog popped up by the progress monitor.
- The second argument is a
String
that describes the nature of the task being monitored. This string is displayed on the dialog.- The third argument is another
String
that provides a changeable status note. The example uses an empty string because the note is updated periodically as the task runs. If you providenull
for this argument, the note is omitted from the dialog. The example updates the note while the task is running each time the timer fires an action event (it updates the monitor's current value at the same time):progressMonitor.setNote(task.getMessage()); progressMonitor.setProgress(task.getCurrent());- The last two arguments provide the minimum and maximum values, respectively, for the progress bar displayed in the dialog.
The first line sets the current position of the progress bar on the dialog. The second indicates that the monitor should pop up a dialog if the task runs longer than two seconds.progressMonitor.setProgress(0); progressMonitor.setMillisToDecideToPopup(2 * ONE_SECOND);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:
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.if (progressMonitor.isCanceled() || task.done()) { progressMonitor.close(); task.stop(); Toolkit.getDefaultToolkit().beep(); timer.stop(); startButton.setEnabled(true); }Deciding Whether to Use a Progress Bar or a Progress Monitor
Use a progress bar if:
- You want more control over the configuration of the progress bar. If you are working directly with a progress bar, you can make it display vertically, you can provide a string for it to display, you can register change listeners on it, and you can provide it with a custom data model.
- Other controls or GUI elements need to be displayed along with the progress bar.
- You need more than one progress bar. With some tasks, you need to monitor more than one parameter. For example, an installation program might monitor disk space usage in addition to how many files have been successfully installed.
- You need to reuse the progress bar. A progress bar can be re-used; a progress monitor cannot. The progress monitor doesn't have a
reset
method, and once themillisToDecideToPopup
timeframe has expired the monitor has done its job.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
- You want an easy way to display progress in a dialog.
- The running task is secondary and the user might not be interested in the progress of the task. Progress monitor provides a way for the user to dismiss the dialog while the task is still running.
- Your task is cancelable. Progress monitor provides a way for the user to cancel the task. All you have to do is call progress monitor's
isCanceled
method to find out if the user pressed the Cancel button.- Your task displays a short message periodically while running. The progress monitor dialog provides the
setNote
method so that the task can provide further information about what it's doing. For example, an installation task might report the name of each file as it's installed.- The task might not take a long time to complete. You decide at what point a running task is taking long enough to warrant letting the user know about it. Progress monitor won't pop up a dialog if the task completes within the timeframe you set.
ProgressMonitorInputStream
class.The Progress Monitoring API
The following tables list the commonly usedJProgressBar
constructors and methods. Other methods you're likely to call are defined by theJComponent
andComponent
classes and include [PENDING: anything in particular for these classes?]. [Link to JComponent and Component discussions.]The API for monitoring progress falls into these categories:
- Setting or Getting the Progress Bar's Constraints/Values
- Fine Tuning the Progress Bar's Appearance
- Configuring the Progress Monitor
- Terminating the Progress Monitor
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 getMaximum()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.
Fine Tuning the Progress Bar's Appearance Method Purpose void setOrientation(int)
int getOrientation()Set or get whether the progress bar is vertical or horizontal. Acceptable values are JProgressBar.VERTICAL
orJProgressBar.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 change the percent string withsetString
.void setString(String)
String getString()Set or get the percent string.
Configuring the Progress Monitor Method Purpose ProgressMonitor(Component, Object, String, int, int)
Create progress monitor and initialize its dialog's parent, description string, status note, and minimum and maximum values. void setMinimum(int)
int getMinimum()Set or get the minimum value of the progress monitor. void setMaximum(int)
int getMaximum()Set or get the maximum value of the progress monitor. 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 setMillisToPopup(int)
int getMillisToPopup()[PENDING: what is this? API docs doesn't say here's a guess....] Set or get the time after which the monitor should popup a dialog regardless of the state of the task. void setMillisToDecideToPopup(int)
int getMillisToDecideToPopup()Set or get the time after which the monitor should popup a dialog if the task has not yet completed.
Terminating the Progress Monitor Method Purpose close()
Close the progress monitor. This hides the dialog. boolean isCanceled()
Determine whether the user pressed the Cancel button. Examples that Monitor Progress
This table shows the examples that useJProgressBar
,ProgressMonitor
, orProgressMonitorInputStream
, and where those examples are described.
Example Where Described Notes ProgressBarDemo.java
This page and How to Use Timers Uses a basic progress bar to show progress on a task running in a separate thread. ProgressMonitorDemo.java
This page Modification of the previous example that uses a progress monitor instead of a progress bar.
Using the JFC/Swing Packages |