views:

72

answers:

7

I can't update my progressbar... this is my code

Thread t=new Thread(new Runnable(){
        public void run(){
            int i=1;
            jProgBar.setMinimum(0);
            jProgBar.setMaximum(100);
            try {
                while(i<=100 || true){
                    jProgBar.setValue(i);
                    i++;
                    Thread.sleep(50);
                }
            }
            catch (InterruptedException ex){
                jProgBar.setValue(jProgBar.getMaximum());
            }
        }
    });
    t.start();

    .... Something code that correctly works

    t.interrupt();

The progress bar state is updated only at the end of thread. Can someone help me??

+4  A: 

Before the sleep, add a call to SwingUtilties.invokeLater() that spawns a thread to fire a firePropertyChange on the progressbar in the EDT.

Paul Tomblin
Yes, this is according to the principle that any changes to the states of components should be done from the Event Dispatch Thread. Swing was apparently designed in this way (single threaded) to avoid too much complexity. Any calls from outside could cause potential interblocking. My understanding is that invokeLater() places a call at the end of a sort of execution queue.
James P.
A: 

Not work!

i've changed my code like follows:

Runnable MyRun = new Runnable() {
        public void run() {
            jProgBar.setMaximum(100);
            jProgBar.setMinimum(0);
            jProgBar.setIndeterminate(false);
            int i=10;
            while (true){
                try {
                    jProgBar.setValue(i);
                    i+=10;
                    SwingUtilities.invokeLater(this);
                    Thread.sleep(50);
                }
                catch (InterruptedException ex) {}
            }
        }
    };

    Thread t=new Thread(MyRun);
    t.start();

.... Something code that correctly works

    t.interrupt();

But nothing...

Maverick-F14
+1  A: 

The best advice for your situation is to use SwingWorker. Check out the API at http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html

Override process method to update value of progress bar ( then it will be done correctly on EDT)

More info can be obtained at http://java.sun.com/products/jfc/tsc/articles/threads/threads2.html

eugener
A: 

Use a model instead of the JProgressBar directly:

DefaultBoundedRangeModel model = new DefaultBoundedRangeModel();
JProgressBar bar = new JProgressBar(model);

// Somewhere else, perhaps in another Thread
model.setValue(i)

The following example works fine:

public static void main(String[] args) throws InterruptedException {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(200, 100);
    frame.setVisible(true);
    final DefaultBoundedRangeModel model = new DefaultBoundedRangeModel();
    frame.add(new JProgressBar(model));
    Thread t = new Thread(new Runnable() {
        public void run() {
            int i = 1;
            model.setMinimum(0);
            model.setMaximum(100);
            try {
                while (i <= 100 || true) {
                    model.setValue(i);
                    i++;
                    Thread.sleep(50);
                }
            } catch (InterruptedException ex) {
                model.setValue(model.getMaximum());
            }
        }
    });
    t.start();

    Thread.sleep(2000);

    t.interrupt();
}
mhaller
Unless he does it on EDT is it not going to work.
eugener
Yes, it works. See BasicProgressBarUI lines 1226-1229 in JDK1.6.0_20, which issues a repaint() resulting in Toolkit.getEventQueue().postEvent(e);
mhaller
+1  A: 

Per eugener, SwingWorker is definitely what you want to be using here, or any time a long-running task is spawned that could otherwise lock up your GUI prior to completion. A full tutorial on using progress bars with SwingWorker is available from Sun^H^H^HOracle here:

http://java.sun.com/docs/books/tutorial/uiswing/components/progress.html

Starchy
A: 

Putting this snippet

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        jProgBar.repaint();
    }
}

Between 'i++' and 'Thread.sleep()' should do the job. To get it compiling, mark jProgBar as 'final'.

Vanya
+1  A: 

Thanks All. I solved in this way

try{
       jProgBar.setIndeterminate(true);
       jProgBar.setStringPainted(true);
       jProgBar.setBorderPainted(true);
       new Thread(new Runnable() {
           public void run() {
               ...
               // here is code that i've to wait
               // after this i stop my jProgressBar
               ...
               jProgBar.setStringPainted(false);
               jProgBar.setBorderPainted(true);
               jProgBar.setIndeterminate(false);
       }
       }).start();
   }
   catch(IllegalStateException ex){
       //some code
   }
Maverick-F14