tags:

views:

176

answers:

4

I'm trying to get a JProgressBar to increment by 1 every 100th of a second, and at the moment I'm using Thread.sleep(100) inside a while statement like so:

    try {
         while (i<=100){
            doTime();

         }
    } catch (InterruptedException ex) {
        Logger.getLogger(SplashScreen.class.getName()).log(Level.SEVERE, null, ex);
    }

public void doTime() throws InterruptedException{


        jLabel1.setText("sleeping");
        Thread.sleep(100);
        jLabel1.setText("start");
        i++;
        pb.setValue(i);
        pb.repaint();

}

and If I debug by doing a System.out.println it displays in real time but the swing GUI freezes until it drops out of the while loop can anyone help?

thanks

matt

+2  A: 

The problem is that you are sleeping the Swing Event thread. You'll want to create a new thread for running the loop, and then have that loop update the progressbar on the swing event thread.

I would use the Swing Worker thread for the loop. Then use invokeLater for updating the progressbar.

Another good swing/thread tutorial.

derivation
+1  A: 

Besides what derivation said, you are sleeping for 100 milliseconds. That means you are only updating every tenth of a second, not every hundredth.

Peter Recore
+4  A: 

As derivation said, you should use SwingWorker. From its javadoc:

"SwingWorker is designed for situations where you need to have a long running task run in a background thread and provide updates to the UI either when done, or while processing. Subclasses of SwingWorker must implement the doInBackground() method to perform the background computation."

With this slight change to ProgressBarDemo.java in the java tutorial, you almost get what you want.

    public Void doInBackground() {
        Random random = new Random();
        int progress = 0;
        //Initialize progress property.
        setProgress(0);
        while (progress < 100) {
            //Sleep for up to one second.
            try {
                //original code: Thread.sleep(random.nextInt(1000));
                Thread.sleep(10);
            } catch (InterruptedException ignore) {}
            //Make random progress.
            //originalcode: progress += random.nextInt(10);
            progress++;
            setProgress(Math.min(progress, 100));
        }
        return null;
    }
Jala
+1  A: 

If doTime() is being called within the Event Dispatch Thread (EDT), which it should since it is calling UI code (jLabel1.setText() and others), then it should not be calling sleep() at all. You do not want to freeze your UI.

The correct way of doing this is to use a timer to wake up in the correct moments (say, every 10 ms) and update the progress. The code by Jala is also a good answer, and it is the official Swing Way of doing things (timers are lower level than SwingWorkers).

tucuxi
+1 Here's a simple example of `javax.swing.Timer` updating a `JLabel` every 100 ms. http://stackoverflow.com/questions/2576353/stop-a-stopwatch/2576909#2576909
trashgod