6.5 Monitoring Progress


By themselves, progress bars are pretty boring. Swing, however, combines progress bars with the dialog capabilities of JOptionPane to create the ProgressMonitor and ProgressMonitorInputStream classes. You can use ProgressMonitor to report on the current progress of a potentially long task. You can use ProgressMonitorInputStream to automatically monitor the amount of data that has been read in with an InputStream. With both, you can define various strings to be posted in the progress monitor dialogs to offer a better explanation of the task at hand.

6.5.1 The ProgressMonitor Class

The ProgressMonitor class is a generic progress dialog box that can be used for practically anything. There are two string descriptions that can be set on a ProgressMonitor dialog box. The first is a static component that can never change; it appears on the top of the dialog and is set in the constructor. The second is a variable string-based property that can be reset at any time. It appears below the static string, slightly above the progress bar. Figure 6-15 shows the structure for this class.

Figure 6-15. ProgressMonitor class diagram
figs/swng2.0615.gif

Once instantiated, the ProgressMonitor dialog (shown in Figure 6-16) does not pop up immediately. The dialog waits a configurable amount of time before deciding whether the task at hand is long enough to warrant the dialog. If it is, the dialog is displayed. When the current value of the progress bar is greater than or equal to the maximum, as specified in the constructor, the progress monitor dialog closes. If you need to close the progress monitor early, you can call the close( ) method. The user can close this dialog as well by pressing OK or Cancel; you can test the canceled property to see if the user wanted to cancel the operation or simply did not care to watch the progress.

Figure 6-16. The ProgressMonitor dialog
figs/swng2.0616.gif

The ProgressMonitor class does not fire any events indicating that it is complete or that the operation was canceled. You should test the isCancelled( ) method each time you call setProgress( ) to see if the user has canceled the dialog.

6.5.1.1 Properties

Table 6-6 shows the properties for the ProgressMonitor class. The canceled property is a boolean that indicates whether the progress monitor has been canceled. This is useful if you need to determine whether the user dismissed the dialog halfway through. The minimum and maximum properties define the range of the progress bar; the progress property is analogous to the progress bar's current value. The note property is a string that can be updated as the progress monitor works; it serves to indicate what the progress monitor is currently doing.

Table 6-6. ProgressMonitor properties

Property

Data type

get

is

set

Default value

canceled

boolean

 

·

 

false

maximum

int

·

 

·

100

millisToDecideToPopup

int

·

 

·

500

millisToPopup

int

·

 

·

2000

minimum

int

·

 

·

0

note

String

·

 

·

 

progress

int

·

 

·

0

As we said, the progress monitor dialog does not pop up immediately. Instead, it waits millisToDecideToPopup milliseconds before estimating how long the current progress might take. If it appears that it will take longer than millisToPopup milliseconds, a progress monitor dialog pops up.

6.5.1.1.1 UIManager properties

Two values used in the ProgressMonitor are extracted from the UIManager settings. ProgressMonitor.progressText (introduced in SDK 1.3) controls the text of the dialog's title bar while OptionPane.cancelButtonText controls the text on the Cancel button. See ProgressMonitorExample below for an example of how to set these properties.

6.5.1.2 Constructor
public ProgressMonitor(Component parentComponent, Object message, String note, int min, int max)

Create a ProgressMonitor dialog box, placed above the component specified as parentComponent. The dialog contains a static message that is constant throughout the life of the dialog (see JOptionPane in Chapter 10 for a discussion of valid values) and a note that changes during the life of the dialog. If the note value is initially null, the note cannot be updated throughout the life of the dialog. The min and max values specify the minimum and maximum of the progress bar.

6.5.1.3 Miscellaneous
public void close( )

Force the ProgressMonitor to shut down, even if it did not complete all of its tasks.

6.5.1.4 Using a progress monitor

The following example shows a ProgressMonitor in action. With it, we simulate updating the dialog with a timer that fires off events every 0.5 seconds. We use the invokeLater( ) method to place the update on the system event queue. The run( ) method of the Update inner class simply increments the progress bar's progress property, updates the text on the progress bar, and updates the counter. The result is shown in Figure 6-16.

// ProgressMonitorExample.java // import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ProgressMonitorExample extends JFrame implements ActionListener {   static ProgressMonitor pbar;   static int counter = 0;   public ProgressMonitorExample( ) {     super("Progress Monitor Demo");     setSize(250,100);     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);     pbar = new ProgressMonitor(null, "Monitoring Progress",            "Initializing . . .", 0, 100);     // Fire a timer every once in a while to update the progress.     Timer timer = new Timer(500, this);     timer.start( );     setVisible(true);   }   public static void main(String args[]) {     UIManager.put("ProgressMonitor.progressText", "This is progress?");     UIManager.put("OptionPane.cancelButtonText", "Go Away");     new ProgressMonitorExample( );   }   public void actionPerformed(ActionEvent e) {     // Invoked by the timer every 0.5 seconds. Simply place     // the progress monitor update on the event queue.     SwingUtilities.invokeLater(new Update( ));   }   class Update implements Runnable {     public void run( ) {       if (pbar.isCanceled( )) {         pbar.close( );         System.exit(1);       }     pbar.setProgress(counter);     pbar.setNote("Operation is "+counter+"% complete");     counter += 2;     }   } }

6.5.2 The ProgressMonitorInputStream

The ProgressMonitorInputStream is a stream filter that allows the programmer to monitor the amount of data read from an input stream. It contains a ProgressMonitor object that the user can access to see how the reading of the input stream is progressing. Figure 6-17 shows the class diagram for this filter.

Figure 6-17. JProgressMonitorInputStream class diagram
figs/swng2.0617.gif

For the most part, the ProgressMonitorInputStream class contains many of the methods found in java.io.InputStream. Like all FilterInputStream objects, you can tie this class together with other filters for better control over the input. Figure 6-18 shows the progress monitor dialog associated with a typical ProgressMonitorInputStream.

Figure 6-18. The ProgressMonitorInputStream dialog
figs/swng2.0618.gif
6.5.2.1 Property

Table 6-7 shows the only property of the ProgressMonitorInputStream. progressMonitor contains the progress monitor defined inside this object. The read-only accessor allows you to change the progress or the note string, as well as close the dialog.

Table 6-7. ProgressMonitorInputStream property

Property

Data type

get

is

set

Default value

progressMonitor

ProgressMonitor

·

   

ProgressMonitor( )

When it's created, the ProgressMonitorInputStream attempts to read the amount of data available and updates the progress monitor's progress property as bytes are read from the stream. This can lead to strange results if you wrap a ProgressMonitorInputStream around some other input stream for which the amount of data waiting to be read isn't well-defined for example, a PipedInputStream. It's a good idea to read small amounts of data from a ProgressMonitorInputStream at a time. This way, the dialog has a chance to update its progress frequently. Finally, as with any blocking request, try not to perform a read( ) while on the event dispatching queue. That way, if the call blocks for an inordinate amount of time, you won't drag down any repainting requests and give the illusion that your application has crashed.

6.5.2.2 Constructor
public ProgressMonitorInputStream(Component parentComponent, Object message, InputStream in)

Create a ProgressMonitorInputStream dialog box, placed above the parentComponent. The dialog contains a static message that is constant throughout the life of the dialog (see JOptionPane in Chapter 10 for a discussion of valid values). The constructor also takes a reference to the target input stream.

6.5.2.3 InputStream methods
public int read( ) throws IOException

Read a single byte and update the progress monitor.

public int read(byte b[]) throws IOException
public int read(byte b[], int off, int len) throws IOException

Read an array of bytes and update the progress monitor.

public long skip(long n) throws IOException

Skip a series of bytes and update the progress monitor.

public void close( ) throws IOException

Close the input stream and the progress monitor.

public void reset( ) throws IOException

Reset the current reading position back to the beginning and update the progress monitor.

6.5.2.4 Using a ProgressMonitorInputStream

Here is a simple example that demonstrates using a ProgressMonitorInputStream class to monitor the progress of loading a file. You can specify the name of the file on the command line as follows:

% java ProgressMonitorInputExample myfile

This program reads in the file a little at a time, dumping the results to the screen. If the file is not found, an error dialog is displayed. Note that we specifically don't try to buffer the input we want "bad" performance to make sure the monitor dialog has time to pop up. (Still, you may need to load a fairly large file.) If you run the program, be sure to load a text file (not a binary file). Here is the source code:

// ProgressMonitorInputExample.java // import java.io.*; import java.awt.*; import javax.swing.*; public class ProgressMonitorInputExample {     public ProgressMonitorInputExample(String filename) {         ProgressMonitorInputStream monitor;         try {             monitor = new ProgressMonitorInputStream(                 null, "Loading "+filename, new FileInputStream(filename));             while (monitor.available( ) > 0) {                 byte[] data = new byte[38];                 monitor.read(data);                 System.out.write(data);             }         } catch (FileNotFoundException e) {             JOptionPane.showMessageDialog(null, "Unable to find file: "                 + filename, "Error", JOptionPane.ERROR_MESSAGE);          } catch (IOException e) {;}     }     public static void main(String args[]) {          new ProgressMonitorInputExample(args[0]);     } } 


Java Swing
Graphic Java 2: Mastering the Jfc, By Geary, 3Rd Edition, Volume 2: Swing
ISBN: 0130796670
EAN: 2147483647
Year: 2001
Pages: 289
Authors: David Geary

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net