Skip to main content

Magic with Merlin: Indeterminate progress bars

A subtle, but important update to JProgressBar

John Zukowski (jaz@zukowski.net), President, JZ Ventures, Inc.
Author photo
John Zukowski conducts strategic Java consulting with JZ Ventures, Inc., offers technical support through AnswerSquad.com, and is working with SavaJe Technologies to develop a next-generation mobile phone platform. His latest books are Mastering Java 2, J2SE 1.4 (Sybex, April 2002) and Learn Java with JBuilder 6 (Apress, March 2002). Reach him at jaz@zukowski.net.

Summary:  Developers use a JProgressBar component to show users how far along a task has progressed. For really long tasks or those where it's difficult to figure out exactly how far along that task is, the Merlin release adds an indeterminate mode to JProgressBar. This month, columnist John Zukowski provides a refresher on using JProgressBar and discusses its new indeterminate mode.

View more content in this series

Date:  18 Nov 2003
Level:  Introductory
Activity:  1973 views

Some changes in the Java 2 SDK, Standard Edition, version 1.4 are big, such as the addition of new components like JSpinner, new layout managers like SpringLayout, or new APIs like the Java Logging API. Other changes, such as slight improvements or tweaks to existing APIs, are less dramatic. This month's tip on the JProgressBar component is of the latter variety. It's subtle, but important.

Basic progress bar usage

JProgressBar is part of the original set of Swing components. It offers a simple way to graphically show a process's completion progress. As the process progresses, a bar extends across the component until the job is completed and the bar is filled. The movement of the bar is usually part of some multithreaded task, which helps to avoid blocking progress from the rest of the application, like regular screen updates. While there's no specific rule that says a progress bar must move in linear steps, as a user I would find it a little weird to see the progress move from 10 percent to 35 percent, then back to 27 percent, then up to 80 percent before ending at 0 percent.

You construct a JProgressBar using one of the five constructors, shown in Listing 1:


Listing 1. JProgressBar constructors
  public JProgressBar()
  public JProgressBar(int orientation) 
  public JProgressBar(int minimum, int maximum)
  public JProgressBar(int orientation, int minimum, int maximum)
  public JProgressBar(BoundedRangeModel model)

JProgressBar lets you initialize the orientation and range of values. Orientation is done through the VERTICAL or HORIZONTAL constants of JProgressBar. HORIZONTAL is the default.

After you create the component and show it on the screen, you kick off a secondary thread to perform the task whose progress needs measuring. You then periodically update the current value of the progress bar with the setValue() method to indicate the current progress of the task. Listing 2 shows a simple example of setValue():


Listing 2. Simple JProgressBar usage
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.*;

public class ProgressSample {
  static class BarThread extends Thread {
    private static int DELAY = 500;
    JProgressBar progressBar;

    public BarThread(JProgressBar bar) {
      progressBar = bar;
    }

    public void run() {
      int minimum = progressBar.getMinimum();
      int maximum = progressBar.getMaximum();
      Runnable runner = new Runnable() {
        public void run() {
          int value = progressBar.getValue();
          progressBar.setValue(value+1);
        }
      };
      for (int i=minimum; i<maximum; i++) {
        try {
          SwingUtilities.invokeAndWait(runner);
          // Our task for each step is to just sleep
          Thread.sleep(DELAY);
        } catch (InterruptedException ignoredException) {
        } catch (InvocationTargetException ignoredException) {
        }
      }
    }
  }
  public static void main(String args[]) {
    // Initialize
    final JProgressBar aJProgressBar = new JProgressBar(0, 100);

    final JButton aJButton = new JButton("Start");

    ActionListener actionListener = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        aJButton.setEnabled(false);
        Thread stepper = new BarThread(aJProgressBar);
        stepper.start();
      }
    };

    aJButton.addActionListener(actionListener);

    JFrame theFrame = new JFrame("Progress Bars");
    theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container contentPane = theFrame.getContentPane();
    contentPane.add(aJProgressBar, BorderLayout.NORTH);
    contentPane.add(aJButton, BorderLayout.SOUTH);
    theFrame.setSize(300, 100);
    theFrame.show();
  }
}

When you first run this code, you'll see a screen similar to Figure 1.


Figure 1. Starting screen
Starting Screen

You click the button to start the secondary task and update the progress bar as it runs. Figure 2 shows the bar in the middle of its run.


Figure 2. Screen showing progress
Screen Showing Progress

Nothing too fancy going on here. The main code creates the GUI with a button and progress bar. When you select the button, it triggers the action to update the progress bar. The progress bar is meant to measure some task. In the example program, that task is to just sleep for a half second, 100 different times.

By default, there is no graphical indication of progress besides the bar. By adding the line of code shown below, you can have the bar show what percentage of the task is completed as the task progresses:

  aJProgressBar.setStringPainted(true);

Figure 3 shows our screen with the new code added:


Figure 3. Showing completion percentage
Showing Percentage

Indeterminate usage

Starting with the Merlin release, JProgressBar supports yet another mode -- indeterminate. You use this mode for long tasks with no fixed number of steps. It shows constant animation to indicate something is going on, but it doesn't indicate what percentage has completed. If -- or when -- you determine how long a task will take, you can switch back to determinate mode. While in indeterminate mode, though, JProgressBar shows a bar that goes back and forth within the display area.

Listing 3 shows an example of this mode. The new method here is just setIndeterminate(). A value of true means indeterminate, while false is normal or determinate.


Listing 3. Indeterminate progress bars
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ProgressSample2 {
  public static void main(String args[]) {
    final JProgressBar aJProgressBar = new JProgressBar(0, 100);
    aJProgressBar.setIndeterminate(true);

    JButton aJButton = new JButton("Toggle");

    ActionListener actionListener = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        boolean indeterminate = aJProgressBar.isIndeterminate();
        aJProgressBar.setIndeterminate(!indeterminate);
      }
    };

    aJButton.addActionListener(actionListener);

    JFrame theFrame = new JFrame("Indeterminate");
    theFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container contentPane = theFrame.getContentPane();
    contentPane.add(aJProgressBar, BorderLayout.NORTH);
    contentPane.add(aJButton, BorderLayout.SOUTH);
    theFrame.setSize(300, 100);
    theFrame.show();
  }
}

Figure 4 shows the associated screen (you'll have to imagine the bar moving back and forth). The button toggles the progress bar between the indeterminate and determinate modes.


Figure 4. Indeterminate mode
Indeterminate

There are two new UI defaults available to allow you to change the repaint interval and cycle time: ProgressBar.repaintInterval and ProgressBar.cycleTime. Changing these settings -- as shown below -- changes the display speed. The cycle time must be an even multiple of the repaint interval, so if the interval is 100, then the cycle time could be 200, 500, or 1000 -- but not 750.

  UIManager.put("ProgressBar.repaintInterval", new Integer(150));
  UIManager.put("ProgressBar.cycleTime", new Integer(1050));

Note that you need to set these settings before you create the progress bar.


Conclusion

There's much more to the JProgressBar, but none of its other features changed with the 1.4 release. We've simply reviewed the old way of using the component and introduced its new features under Merlin. You might also consider using ProgressMonitor or ProgressMonitorInputStream to monitor the progress of those long tasks. Both take advantage of the JProgressBar internally.


Resources

About the author

Author photo

John Zukowski conducts strategic Java consulting with JZ Ventures, Inc., offers technical support through AnswerSquad.com, and is working with SavaJe Technologies to develop a next-generation mobile phone platform. His latest books are Mastering Java 2, J2SE 1.4 (Sybex, April 2002) and Learn Java with JBuilder 6 (Apress, March 2002). Reach him at jaz@zukowski.net.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=10887
ArticleTitle=Magic with Merlin: Indeterminate progress bars
publish-date=11182003
author1-email=jaz@zukowski.net
author1-email-cc=jaloi@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers