JProgressBar isn't progressing

So i'm trying to make a downloader which shows the progress of the download with a progress bar. But i'm having problems since it doesn't actually update the progress bar. Basically it stays white, when it is meant to be blue. If anyone could help, code is below.

JProgressBar progressBar = new JProgressBar(0, ia);
con.add(progressBar, BorderLayout.PAGE_START);
con.validate();
con.repaint();
progressBar = new JProgressBar(0, ia);
progressBar.setValue(0);
System.out.print("Downloading Files");
while ((count = in.read(data, 0, downloadSpeed)) != -1){
    fout.write(data, 0, count);
    if (count >= 2){
        progressBar.setString("Downloading : " + ia + " @ " + count + "Kbs per second");
    } else {
        progressBar.setString("Downloading : " + ia + " @ " + count + "Kb per second");
    }
    progressBar.setValue(count);
    con.add(progressBar, BorderLayout.PAGE_START);
    try{
        Thread.sleep(1000);
    } catch (Exception e){}
}

Solution 1:

As @happyburnout has pointed out, you'd be better of processing you download in a separate thread, using a SwingWorker is probably the best solution for what you are doing.

The main reason is you're blocking the Event Dispatching Thread (AKA EDT) from running, preventing any repaint requests (and other UI important things) from been processed.

You should have a read through

  • Concurrency in Swing
  • Worker Threads and Swing Worker

Now this is taken almost directly from the API docs, but gives a basic idea of a SwingWoker with a JProgressBar

The "Worker"...

public class Worker extends SwingWorker<Object, Object> {

    @Override
    protected Object doInBackground() throws Exception {

        // The download code would go here...
        for (int index = 0; index < 1000; index++) {

            int progress = Math.round(((float)index / 1000f) * 100f);
            setProgress(progress);

            Thread.sleep(10);

        }

        // You could return the down load file if you wanted...
        return null;

    }

The "progress pane"

public class ProgressPane extends JPanel {

    private JProgressBar progressBar;

    public ProgressPane() {

        setLayout(new GridBagLayout());
        progressBar = new JProgressBar();

        add(progressBar);

    }

    public void doWork() {

        Worker worker = new Worker();
        worker.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if ("progress".equals(evt.getPropertyName())) {
                    progressBar.setValue((Integer) evt.getNewValue());
                }
            }

        });

        worker.execute();

    }

}

Remember the golden rules of Swing

  • Never, never, never update a UI component from any Thread other then the EDT
  • Always perform time consuming tasks on a different Thread
  • (Something, something, something about layout managers - that's more of a personal thing ;))

And you will have a happy and easy time with Swing :D

Solution 2:

Use a combination with SwingWorker. See an example here: SwingWorker and Progress Bar

@Hovercraft: You're right. Allow me to refer to the corresponding SwingWorker page of JavaDoc, in my opinion this explains the situation best.