I l@ve RuBoard |
![]() ![]() |
6.5 Monitoring ProgressBy 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 ClassThe 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![]() 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![]() 6.5.1.1 PropertiesTable 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.
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 propertiesTwo 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
6.5.1.3 Miscellaneous
6.5.1.4 Using a progress monitorThe 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 ProgressMonitorInputStreamThe 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![]() 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![]() 6.5.2.1 PropertyTable 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.
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
6.5.2.3 InputStream methods
6.5.2.4 Using a ProgressMonitorInputStreamHere 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]); } } |
I l@ve RuBoard |
![]() ![]() |