The JFC Swing Tutorial: A Guide to Constructing GUIs (2nd Edition)
< Day Day Up > |
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. For example, the following code causes the wait cursor to be displayed when the cursor is over container (including any components it contains that have no cursor specified): container.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); To convey how complete a task is, you can use a progress bar like the one in Figure 41. Figure 41. Standard 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. As of 1.4, 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 Figure 42. Figure 42. Indeterminate progress bar.
Swing provides three classes to help you use progress bars: JProgressBar
A visible component to graphically display how much of a total task has completed. The next section has information and an example of using a typical progress bar. The section after that, Using Indeterminate Mode (page 303), 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 Using Progress Monitors (page 305) 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 The Java Tutorial trail, "I/O: Reading and Writing (but no 'rithmetic)." [106] You can get the stream's progress monitor with a call to getProgressMonitor and configure it as described in Using Progress Monitors (page 305). [106] This trail is on the CD at: JavaTutorial/essentials/index.html and on this book's CD. After you see a progress bar and a progress monitor in action, Deciding Whether to Use a Progress Bar or a Progress Monitor (page 307) can help you figure out which is appropriate for your application. Using Determinate Progress Bars
Figure 43 is 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. Figure 43. A screenshot of the ProgressBarDemo example. Note the use of the wait cursor (the hourglass).
Try This:
Below is the code from ProgressBarDemo.java that creates and sets up the progress bar: //Where member variables are declared: JProgressBar progressBar; //...where the GUI is created: 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 ProgressBarDemo 's task by clicking the Start button. Once the task has begun, a timer (an instance of the javax.swing.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()); String s = task.getMessage(); if (s != null) { taskOutput.append(s + newline); taskOutput.setCaretPosition( taskOutput.getDocument().getLength()); } if (task.isDone()) { Toolkit.getDefaultToolkit().beep(); timer.stop(); startButton.setEnabled(true); setCursor(null); //turn off the wait cursor progressBar.setValue(progressBar.getMinimum()); } } The boldface line of code gets the amount of work completed by the task and updates the progress bar with that value. Thus, 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 and the cursor.
Using Indeterminate Mode
Adding indeterminate mode to ProgressBarDemo requires just a few lines of code (shown in bold): //Where the progress bar is created: progressBar.setStringPainted(true); //get space for the string progressBar.setString(""); //but don't paint it . . . //In the actionPerformed method of the timer's action listener: progressBar.setValue(task.getCurrent()); String s = task.getMessage(); if (s != null) { if (progressBar.isIndeterminate()) { progressBar.setIndeterminate(false); progressBar.setString(null); //display % string } taskOutput.append(s + newline); taskOutput.setCaretPosition( taskOutput.getDocument().getLength()); } if (task.isDone()) { ... progressBar.setString(""); //hide % string } . . . //In the event handler that handles Start button clicks: progressBar.setIndeterminate(true); The most important code additions are calls to the setIndeterminate method. When the user clicks the Start button, setIndeterminate(true) is invoked so that the user can tell that the task has started, even before any meaningful information about the task's progress can be conveyed. Once the progress bar has some concrete status to display, a call to set-Indeterminate(false) switches the progress bar back into its normal mode. The isIndeterminate method is used to test the progress bar's current state. 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 arbitarily 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. Later, when the progress bar switches from indeterminate to determinate mode, invoking setString(null) makes the progress bar display its default string. One change we did not make was removing the call to progressBar.setValue from the timer's action handler. 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:
Using Progress Monitors
Now let's rewrite ProgressBarDemo to use a progress monitor instead of a progress bar. (See Figure 44.) Figure 44. A screenshot of the new demo program, ProgressMonitorDemo .
Try This:
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:
The Progress Monitoring API
Tables 56 through 61 list the commonly used API for 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 (page 53). Note that ProgressMonitor is a subclass of Object and is not a visual component. Also see the API documentation for the JProgressBar and ProgressMonitor classes at: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JProgressBar.html http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/ProgressMonitor.html Table 56. Creating the Progress Bar
Table 57. Setting or Getting the Progress Bar's Constraints/Values
Table 58. Controlling the Progress Bar's Appearance
Table 59. Creating the Progress Monitor
Table 60. Configuring the Progress Monitor
Table 61. Terminating the Progress Monitor
Examples That Monitor Progress
The following examples use JProgressBar or ProgressMonitor .
|
< Day Day Up > |