Search code examples
javaswingjprogressbar

JProgressBar.setMaximum(int) sometimes doesn't seems to work


I have a JProgressBar that I need to set a new minimum, maximum and progress value each time a task of a queue is done, using the code below:

this.progressBar.setMinimum(minimum);
this.progressBar.setMaximum(maximum);
this.progressBar.setValue(progress);

But, I noticed that sometimes, the setMaximum(int) method doesn't seems to work, because the progress bar still working with the old maximum value.

Then I wrote some test code and ran it:

progressBar.setMaximum(10);
System.out.println(progressBar.getMaximum());

Sometimes it prints 10 as expected, and sometimes prints the old value: anything different from 10.

I spent hours on Google and javadocs, tried to call revalidate() and repaint() on JProgressBar's parent, and nothing. I also tried to call Thread.sleep(10) to wait AWT threads to run another tasks and didn't work.

Any ideas?

EDIT: Provided some more code:

/* Applet that construct the view and init a Thread. */
public class FastApplet extends Applet {
    private JProgressBar progressBar;
    private JPanel panel;
    private Runnable runnable;

    @Override
    public void init() {
        try {
            java.awt.EventQueue.invokeAndWait(new Runnable() {
                @Override
                public void run() {
                    createAndShowGUI();
                    initThreads();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void createAndShowGUI() {
        panel = new JPanel();
        progressBar = new JProgressBar();
        progressBar.setStringPainted(true);
        panel.add(progressBar);
    }

    private void initThreads() {        
        runnable = new MyRunnable(progressBar);     
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

/* Runnable that update progress and call setMaximum(int) on JProgressBar */
public class MyRunnable {
    private int progress;
    private final JProgressBar progressBar;

    MyRunnable(JProgressBar progressBar) {
        this.progressBar = progressBar;
    }

    @Override
    public void run() {
        // do the tasks and update the progressBar using progressBar.setValue(progress)
        // when done, reset the progress bar with the a new maximum:
        defineNewProgressBar(0, 0, newMaximum);
    }

    public void defineNewProgressBar(int progress, int minimum, int maximum) {
        this.progress = progress;

        Component component = progressBar.getParent();
        JPanel panel = (JPanel) component;

        this.progressBar.setMinimum(minimum);
        this.progressBar.setMaximum(maximum);
        this.progressBar.setValue(progress);

        panel.revalidate();
        panel.repaint();
    }
}

Solution

  • You wrote in your comments that you call setMaximum() not from the EDT. You should call it from the EDT like this:

    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            progressBar.setMaximum(10);
        }
    });
    

    If you use Java8, you can do this with using a lambda expression:

    SwingUtilities.invokeLater(()->progressBar.setMaximum(10));