doEvents in Java

Is there a statement in Java that is similar to the Visual Basic DoEvents statement?  I would like to update a progress bar while running a series of tasks.  After each task I set a progress bar value but the progress bar is not updated until all of the tasks complete.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

In java you need to register listeners for events you want to track. So if you wish to track the Mouse events like mousedown, up a certain class, you have to implement the MouseListener interface. What that means is your class must implement the methods in the MouseListener interface. Once you do that, in the main or elsewhere you add your object as a listener. For. e.g. in your Frame class you do this.addListener(<object of your class which implements the MouseListener interface>....when you do this, for all mouse events your class' methods will be invoked.....more work than the DoEvents of VB...but neat....
for your purpose, if you're using a JProgressBar, you might just have to call a setValue and then repaint everytime a task might be missing the repaint part
You may consider letting the process you are following in the progress bar run in another thread.

Jim CakalicSenior Developer/ArchitectCommented:
You are probably doing your processing as part of some event that occurred in your UI, right? Like maybe the user presses a JButton. You have an ActionListener registered on the JButton and your actionPerformed method looks something like:

   public void actionPerformed(ActionEvent e) {
       setup JProgressBar
       task loop:
           do a task
           update the progress bar

Let me know if I'm off base here. What is happening is that AWT (and thus Swing) handles events on a single thread which is created when your UI is "realized". That thread does all the event dispatching for Swing/AWT components used in your application. When an event like a button press occurs, it delivers it to the target component, your JButton, which gets all it's registered ActionListeners and calls their actionPerformed methods one at a time. This is all happening on the AWT event dispatch thread. Since requests to repaint are queued on the EventQueue serviced by the dispatch thread, the fact that you are blocking that thread from going about it's normal activities "freezes" your UI until the actionPerformed method completes.

The best way to work around that is to start another thread on which the non-UI processing will be done. The first step is to create a Runnable with the work to be done in it's run method. Use that Runnable (created here from an anonymous inner class) to construct a new Thread object and start the Thread.

   private JProgressBar bar;
   public void actionPerformed(ActionEvent e) {
           ... setup the progress bar, put it in the containment hierarchy,
           ... whatever you're already doing is probably okay as long as the
           ... JProgressBar variable is an instance field of the class

           Thread th = new Thread(new Runnable() {
               public void run() {
                   task loop:
                       do a task
                       update the progress bar

This introduces a new wrinkle, though. During the processing we want to update a JProgressBar. Before we moved this code to another thread, it was executing in the event dispatch thread by virtue of the fact that it was occuring in the actionPerformed method. But now it is running on another thread. Great. Unfortunately, it means that you cannot update the JProgressBar component directly by calling its methods. This is because Swing is not thread-safe. Swing components should only be updated from the event dispatch thread.

How to do it then? Use the SwingUtilities class. Here is a basic skeleton that shows what you would do in the loop of your run method above.

  while (continueWorking) {
      ... do some work
      // time to update progress
      private class ProgressUpdater implements Runnable {
          private JProgressBar _bar;
          private int _value;

          ProgressUpdater(JProgressBar bar, int value) {
              _bar = bar;
              _value = value;
          public void run() {

      try {
          Runnable updater = new ProgressUpdater(pbar, n);
      } catch (Exception e) {
          // ignore or do whatever

      ... maybe more work

The basics of this are that we have some bit of code that we want to be invoked on the event dispatch thread. The way SwingUtilities lets us do that is by putting the code we want invoked in the run method of a Runnable object which it will then put on the EventQueue. The invokeAndWait method will wait until the requested action has occurred -- probably what you want. There is another invokeLater method which queues the event and continues. Using that will probably result in stalling again because your work thread could possibly get too much of the available CPU and prevent the UI from updating in a timely manner.

Anyway, the assumption I made here was that the JProgressBar object was available -- probably as an instance variable. You probably wouldn't need to pass them to the constructor of the ProgressUpdater but I showed that happening for completeness. The value n is the progress bar value you went to set. It is definitely best that these be passed as arguments like this. You have to do it in a constructor because the run method doesn't take any arguments.

You could move the ProgressUpdater class definition out of the method if you felt better about it. Just so long as it remains in the same class as the rest of the code. Not just in the same source file. It should be a private member of the same class.

Let me know if you have any problem with this and I'll help you work through it. I didn't test this code but it is cut and paste from working code that I have. If you'd like additional material on this topic, you might have a look at the Java Tutorial:

Of course, I'd be remiss if I didn't mention that JComponent declares a paintImmediately method which "Paints the specified region in this component and all of its descendants that overlap the region, immediately. It's rarely necessary to call this method. In most cases it's more efficient to call repaint, which defers the actual painting and can collapse redundant requests into a single paint call. This method is useful if one needs to update the display while the current event is being dispatched." Here is an example of how to call this method:

    JProgressBar bar = ...

Best regards,
Jim Cakalic

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rosscAuthor Commented:

You are right, the problem is that the GUI is not being updated until all of the processes have completed.  I used your code and move the processes to another thread but the progress bar still didn't update until everything completed.  To be sure the problem wasn't with the progress bar, I added code to update a label during processing and it also didn't change until all of the processes completed.

I even tried using a progress monitor but it never appeared.  Could be that I got the code for the progress monitor wrong though.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.