简体   繁体   中英

Handling ProgressBar in Java Swing

I am building an utility using swing, where I have requirement to run progress bar while utility is running backend activities. Progress bar should stop once the activity is over indicating user that utility is ready for next actions.

In the below code I have added one button and one progress bar and trying to control the progress bar in 5 secs iteration. But, lookslike 'action Performed" event not taking the iteration. In this case it never trigger progress bar. If I mention only "jProgressBar1.setIndeterminate(true);" then I see progress bar on clicking the button. So, please help me on how to control the progress bar in another button event.

public class SampleSwingExample extends javax.swing.JFrame {

/**
 * Creates new form NewJFrame
 */
public SampleSwingExample() {
    initComponents();
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jProgressBar1 = new javax.swing.JProgressBar();
    jButton1 = new javax.swing.JButton();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jButton1.setText("jButton1");
    jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            try {
                jButton1ActionPerformed(evt);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap(128, Short.MAX_VALUE)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                    .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGap(126, 126, 126))
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                    .addComponent(jButton1)
                    .addGap(145, 145, 145))))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(100, 100, 100)
            .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(18, 18, 18)
            .addComponent(jButton1)
            .addContainerGap(133, Short.MAX_VALUE))
    );

    pack();
}// </editor-fold>                        

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) throws InterruptedException {                                         
    // TODO add your handling code here:
    
    jProgressBar1.setIndeterminate(true); 
    Thread.sleep(5000);
    jProgressBar1.setIndeterminate(false); 
    Thread.sleep(2000);
    jProgressBar1.setIndeterminate(true); 
    Thread.sleep(5000);
    jProgressBar1.setIndeterminate(false); 
}                                        

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(SampleSwingExample.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(SampleSwingExample.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(SampleSwingExample.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(SampleSwingExample.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new SampleSwingExample().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JButton jButton1;
private javax.swing.JProgressBar jProgressBar1;
// End of variables declaration                   

}

any help highly appreciated. Thanks

You should really read up on how to do background jobs on Swing. The interface in Swing runs on an Event Dispatch Thread (EDT). The EDT must not stop , or your interface will become unresponsive. But, once you have other threads, only the EDT is allowed to touch interface elements. So this code is a Very Bad Idea, because it makes the interface non-responsive:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) 
        throws InterruptedException {                                         

    jProgressBar1.setIndeterminate(true); 
    Thread.sleep(5000);                      // <-- interface unresponsive
    jProgressBar1.setIndeterminate(false); 
    Thread.sleep(2000);                      // <-- interface unresponsive
    jProgressBar1.setIndeterminate(true); 
    Thread.sleep(5000);                      // <-- interface unresponsive
    jProgressBar1.setIndeterminate(false); 
}

Instead, you should launch background jobs in a different thread, and let them notify the UI as needed:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    Runnable r = () -> {
        signalProgress(true);
        Thread.sleep(5000);
        signalProgress(false);
        Thread.sleep(2000);
        signalProgress(true);
        Thread.sleep(5000);
        signalProgress(false);

    };
    new Thread(r).start(); // starts a new thread that runs 'r'
}

// this code can be called from any thread
public void signalProgress(final boolean indeterminate) {
    // because SwingUtils.invokeLater executes code safely in the EDT
    // without invokeLater, the interface state could become corrupted
    SwingUtils.invokeLater(() -> jProgressBar.setIndeterminate(indeterminate));
}

Note that there are better ways of doing this. For example, SwingWorker was created to simplify launching background tasks from Swing without messing up the rules of the EDT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM