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 .
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.
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.
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.
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(); 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)); 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.