1

I'm just trying to iterate in for loop and updating values of JProgressBar inside the loop, initiating SwingUtilities.invokeLater.. but it's only updating after completion. Below is my simple code:

import java.awt.Color;
import java.awt.Rectangle;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ProgressBar extends JApplet {
    JProgressBar pg = null;
    JPanel panel = null;
    JButton start = null;
    int i;

    public void init() {
        pg = new JProgressBar(0, 100);
        pg.setStringPainted(true);
        this.setSize(1200, 600);
        this.setLayout(null);
        panel = new JPanel();
        panel.setLayout(null);
        panel.setBackground(Color.white);
        this.setContentPane(panel);
        this.setVisible(true);
        pg.setBounds(new Rectangle(630, 20, 150, 30));
        add(pg);


        start = new JButton("start");
        start.setBounds(new Rectangle(330, 20, 200, 30));
        start.setBackground(Color.lightGray);
        panel.add(start);

        start.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                pg.setValue(0);
                pg.setStringPainted(true);

                for (i = 0; i <= 100; i = i + 1) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            try {
                                pg.setValue(i);
                                java.lang.Thread.sleep(100);
                            } catch (Exception e) {}
                        }
                    });
                }
            }
        });
    }
}

How to reflect the updation of progress bar in incrementing way as it's updating only 100% after for loop completion.

Sushil
  • 2,837
  • 4
  • 21
  • 29
Ashish Kataria
  • 520
  • 3
  • 11
  • 31
  • 2
    `}});}}});}}` There is no need for that level of 'shortening source'. Readability is better. Please use a consistent and logical indent for code blocks. – Andrew Thompson Jun 29 '12 at 11:43

2 Answers2

6

You have to process any calculation/handling stuff in a separate thread and update UI within the Event Dispatch Thread (EDT):

    start.addActionListener ( new ActionListener ()
    {
        public void actionPerformed ( ActionEvent e )
        {
            pg.setValue ( 0 );
            pg.setStringPainted ( true );
            new Thread ( new Runnable ()
            {
                public void run ()
                {
                    for ( i = 0; i <= 100; i = i + 1 )
                    {
                        SwingUtilities.invokeLater ( new Runnable ()
                        {
                            public void run ()
                            {
                                pg.setValue ( i );
                            }
                        } );
                        try
                        {
                            java.lang.Thread.sleep ( 100 );
                        }
                        catch ( Exception e )
                        {
                            //
                        }
                    }
                }
            } ).start ();

        }
    } );

Any action/mouse/key and other listeners methods are always executed within the EDT thread, so you have to move your code into a separate thread. Otherwise you will do all the calculations/handling inside the EDT thread (and that causes the UI stuck).

Mikle Garin
  • 10,083
  • 37
  • 59
4

You are blocking the EDT (Event Dispatching Thread) which is why the progress bar cannot update itself. Your for-loop will push 100 InvocationEvent's on the EventQueue. These 100 events will occur in the order you put them on the queue. When you update the value, a repaint event is pushed on the EventQueue, but that repaint event will only occur after all your InvocationEvent's have been performed.

  1. Never put a Thread.sleep inside the EDT (it blocks the UI and gives a poor user experience)
  2. Put your long-running operations in a SwingWorker
  3. Or use a Swing timer for repetitive tasks
Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117