Search code examples
javamultithreadingswingcompiler-errorsjprogressbar

How to display progress bar? multithreading java


I'm a beginner in java so sorry if I'm asking a stupid question , but how do I make a new thread in my gui class that would create a progress bar. I have a class named progress and made a new thread in my gui class using the constructor that I have created. But for some reason, I am getting a strange error:

"constructor progress in class NewJFrame.progress cannot be applied to given types;
  required: no arguments
  found: JProgressBar
  reason: actual and formal argument lists differ in length   

NewJframe.java

 private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
           if (jRadioButton1.isSelected()){   

          App m = new App();


      Thread t1 = new Thread(new progress(jProgressBar1));
      m.sendPingRequest2("104.160.142.3",jTextPane1,jTextPane2,jTextField1);


} 
    }    

progress.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author User
 */


import javax.swing.JProgressBar;
public class progress implements Runnable {


      private static int DELAY = 500;


  JProgressBar progressBar;



  public  progress (JProgressBar bar) {
    progressBar = bar;
  }


  public void run() {
    int minimum = progressBar.getMinimum();
    int maximum = progressBar.getMaximum();
    for (int i = minimum; i < maximum; i++) {
      try {
        int value = progressBar.getValue();
        progressBar.setValue(value + 1);

        Thread.sleep(DELAY);
      } catch (InterruptedException ignoredException) {
      }
    }
  }
}

Solution

  • This:

    Thread t1= new progress ( jProgressBar1);
    

    Should be:

    Thread t1 = new Thread(new progress(jProgressBar1));
    

    since your progress class implements Runnable and does not extend Thread.

    Also your error message is strange:

    constructor progress in class NewJFrame.progress cannot be applied to given types

    suggesting that the problem resides within the constructor of the NewJFrame.progress class, a class that looks to be nested within the NewJFrame class. If this is so, get rid of the nested class and only deal with the free-standing progress (re-name it "Progress" please) class.


    But having said that, your code has potential problems as you're changing the state of the JProgressBar, a Swing component, directly from within a background thread, and this is not Swing thread-safe. Much better to use a SwingWorker and link it to the JProgressBar's state as per the JProgressBar standard tutorial (check the link please).

    For example:

    import java.awt.event.KeyEvent;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.TimeUnit;
    
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class ProgressFun extends JPanel {
        private JProgressBar progressBar = new JProgressBar(0, 100);
    
        public ProgressFun() {
            progressBar.setStringPainted(true);
            final JButton startProgress = new JButton("Start Progress");
            startProgress.setMnemonic(KeyEvent.VK_S);
            startProgress.addActionListener(l -> {
                startProgress.setEnabled(false);
                progressBar.setValue(0);
                final MyWorker myWorker = new MyWorker();
                myWorker.execute();
    
                myWorker.addPropertyChangeListener(pcEvent -> {
                    if (pcEvent.getPropertyName().equals("progress")) {
                        int value = (int) pcEvent.getNewValue();
                        progressBar.setValue(value);
                    } else if (pcEvent.getNewValue() == SwingWorker.StateValue.DONE) {
                        startProgress.setEnabled(true);
                        try {
                            myWorker.get();
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                });
            });
    
            add(progressBar);
            add(startProgress);
        }
    
        private static void createAndShowGui() {
            ProgressFun mainPanel = new ProgressFun();
    
            JFrame frame = new JFrame("Progress Fun");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    
    class MyWorker extends SwingWorker<Void, Integer> {
    
        @Override
        protected Void doInBackground() throws Exception {
            int progress = 0;
            setProgress(progress);
            while (progress < 100) {
                progress += (int)(5 * Math.random());
                progress = Math.min(progress, 100);
                TimeUnit.MILLISECONDS.sleep((int) (500 * Math.random()));
                setProgress(progress);
            }
            return null;
        }
    }
    

    As an aside, you will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.