28.3. Layout Managers

 

[Page 805 ( continued )]

24.18. (Optional) JProgressBar

JProgressBar is a component that displays a value graphically within a bounded interval. A progress bar is typically used to show the percentage of completion of a lengthy operation; it comprises a rectangular bar that is "filled in" from left to right horizontally or from bottom to top vertically as the operation is performed. It provides the user with feedback on the progress of the operation. For example, when a file is being read, it alerts the user to the progress of the operation, thereby keeping the user attentive.

JProgressBar is often implemented using a thread to monitor the completion status of other threads. The progress bar can be displayed horizontally or vertically, as determined by its orientation property. The minimum , value , and maximum properties determine the minimum, current, and maximum lengths on the progress bar, as shown in Figure 24.28. Figure 24.29 lists frequently used features of JProgressBar .

Figure 24.28. JProgressBar displays the progress of a task.


Figure 24.29. JProgressBar is a Swing component with many properties that enable you to customize a progress bar.
(This item is displayed on page 806 in the print version)

To demonstrate JProgressBar , let us write a GUI application that copies files. A progress bar is used to show the progress of the copying operation, as shown in Figure 24.30.

Figure 24.30. The user enters the files in the text fields and clicks the Copy button to start copying files.
(This item is displayed on page 806 in the print version)


Place a JProgressBar in the north of the frame. Place a button in a panel, and place the panel in the south of the frame. Place the two text fields in two panels, set the titles on the borders of the panels, and place the panels in another panel of the GridLayout with two rows. Place the panel in the center of the frame.


[Page 806]

While copying the data from a source file to a destination file on one thread, the progress bar is updated on another thread. You need to create a thread that copies a file and another thread that updates the progress bar. Every time some bytes of the file are copied , the current value in the progress bar is updated to show the progress.

Create a main class named CopyFile that lays out the user interface. Declare an inner class named CopyFileTask that implements Runnable to copy files. When the Copy button is pressed, a thread for copying a file is created and started in line 41. The progress bar is updated in line 87 as a file is being copied. The complete program is given in Listing 24.13.

Listing 24.13. CopyFile.java
(This item is displayed on pages 806 - 808 in the print version)
 1   import   java.awt.*; 2   import   java.awt.event.*; 3   import   javax.swing.*; 4   import   javax.swing.border.*; 5   import   java.io.*; 6 7   public class   CopyFile   extends   JFrame { 8   private   JProgressBar jpb =   new   JProgressBar(); 

[Page 807]
 9   private   JButton jbtCopy =   new   JButton(   "Copy"   ); 10   private   JTextField jtfFrom =   new   JTextField(); 11   private   JTextField jtfTo =   new   JTextField(); 12 13   public   CopyFile() { 14 JPanel jPanel2 =   new   JPanel(); 15 jPanel2.setLayout(   new   BorderLayout()); 16 jPanel2.setBorder(   new   TitledBorder(   "From"   )); 17 jPanel2.add(jtfFrom, BorderLayout.CENTER); 18 19 JPanel jPanel3 =   new   JPanel(); 20 jPanel3.setLayout(   new   BorderLayout()); 21 jPanel3.setBorder(   new   TitledBorder(   "To"   )); 22 jPanel3.add(jtfTo, BorderLayout.CENTER); 23 24 JPanel jPanel1 =   new   JPanel(); 25 jPanel1.setLayout(   new   GridLayout(   2   ,   1   )); 26 jPanel1.add(jPanel2); 27 jPanel1.add(jPanel3); 28 29 JPanel jPanel4 =   new   JPanel(); 30 jPanel4.add(jbtCopy); 31 32   this   .add(jpb, BorderLayout.NORTH); 33   this   .add(jPanel1, BorderLayout.CENTER); 34   this   .add(jPanel4, BorderLayout.SOUTH); 35 36 jpb.setStringPainted(   true   );  // Paint the percent in a string  37 38 jbtCopy.addActionListener(   new   ActionListener() { 39   public void   actionPerformed(ActionEvent e) { 40  // Create a thread for copying files  41   new   Thread(   new   CopyFileTask()).start(); 42 } 43 }); 44 } 45 46   public static void   main(String[] args) { 47 CopyFile frame =   new   CopyFile(); 48 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 49 frame.setTitle(   "CopyFile"   ); 50 frame.setSize(   400   ,   180   ); 51 frame.setVisible(   true   ); 52 } 53 54  // Copy file and update progress bar in a separate thread  55   class   CopyFileTask   implements   Runnable { 56   private int   currentValue; 57 58   public void   run() { 59 BufferedInputStream in =   null   ; 60 BufferedOutputStream out =   null   ; 61   try   { 62  // Create file input stream  63 File inFile =   new   File(jtfFrom.getText().trim()); 64 in =   new   BufferedInputStream(   new   FileInputStream(inFile)); 65 66  // Create file output stream  67 File outFile =   new   File(jtfTo.getText()); 68 out =   new   BufferedOutputStream(   new   FileOutputStream(outFile)); 

[Page 808]
 69 70  // Get total bytes in the file  71   long   totalBytes = in.available(); 72 73  // Start progress meter bar  74 jpb.setValue(     ); 75 jpb.setMaximum(   100   ); 76 77   int   r; 78   long   bytesRead =     ; 79  // You may increase buffer size to improve IO speed  80   byte   [] b =   new byte   [   10   ]; 81   while   ((r = in.read(b,     , b.length)) !=   -1   ) { 82 out.write(b,     , r); 83 bytesRead += r; 84 currentValue = (   int   )(bytesRead *   100   / totalBytes); 85 86  // Update the progress bar  87 jpb.setValue(currentValue); 88 } 89 } 90   catch   (FileNotFoundException ex) { 91 ex.printStackTrace(); 92 } 93   catch   (IOException ex) { 94 ex.printStackTrace(); 95 } 96   finally   { 97   try   { 98   if   (in !=   null   ) in.close(); 99   if   (out !=   null   ) out.close(); 100 } 101   catch   (Exception ex) {} 102 } 103 } 104 } 105 } 

The class CopyFileTask is a task class. The program creates a task for copying a file on a separate thread. What would happen if copying a file is not run on a separate thread? The progress bar will not be updated until the copy ends. This is because the operation for repainting the progress bar runs on the thread with the actionPerformed method. As long as the copy operation continues, the progress bar never gets a chance to be repainted. Running the copy operation on a separate thread will enable the progress bar to be repainted simultaneously with the copy operation.