Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 

Swing Chapter 13. (The basics) Progress Bars, Sliders, and Scroll Bars. Easy for reading, Click here!

Custom Search
Swing Chapter 13. (The basics) Progress Bars, Sliders, and Scroll Bars. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 1/5 



Next Page (2/5) Next Page

Chapter 13. Progress Bars, Sliders, and Scroll Bars

Subpages: 1. JBounded-range components overview 
2.
Basic JScrollBar example 
3.
JSlider date chooser 
4. JSliders in a JPEG image editor 
5. JProgressBar in an FTP client application 

In this chapter:

  •          Bounded-range components overview
  •          Basic JScrollBar example
  •          JSlider date chooser
  •          JSliders in a JPEG image editor
  •          JProgressBar in an FTP client application

13.1  Bounded-range components overview

JScrollBar, JSlider, and JProgressBar provide visualization and selection within a bounded interval, allowing the user to conveniently select a value from that interval, or simply observe its current state. In this section we'll give a brief overview of these components and the significant classes and interfaces that support them.

13.1.1  The BoundedRangeModel interface

abstract interface javax.swing.BoundedRangeModel

The BoundedRangeModel interface describes a data model used to define an integer value between minimum and maximum values. This value can have a subrange called an extent, which can be used to define the size of, for instance, a scrollbar "thumb." Often the extent changes dynamically corresponding to how much of the entire range of possible values is visible. Note that the value can never be set larger than the maximum or minimum values, and the extent always starts at the current value and never extends past the maximum. Another property called valueIsAdjusting declared and expected to be true when the value is in the state of being adjusted.

Implementations are expected to fire ChangeEvents when any of the minimim, maximum, value, extent, or valueIsAdjusting properties change state. Thus, BoundedRangeModel includes method decarations for adding and removing ChangeListeners: addChangeListener() and removeChangeListener(). This model is used by JProgressBar, JSlider, and JScrollBar.

UI Guideline : Why choose a bounded range component

The bounded range components are essentially analog devices in nature. They are good at providing relative, positional, approximate or changing (in time) data. They are also excellent at visually communicating the bounds or limits of a data selection and at communicating percentage of the whole through approximate visual means. Where you have several values which share the same bounds e.g. RGB values for a Color Chooser, then you can easily communicate relative values of the three choices through use of a bounded range component. The position of each component shows the relative value of one against the other.

So use bounded range components when there is advantage in communicating the range of values and an approximate, relative, position or changing value needs to be communicated to the User.

13.1.2  DefaultBoundedRangeModel

class javax.swing.DefaultBoundedRangeModel

DefaultBoundedRangeModel is the default concrete implementation of the BoundedRangeModel interface. The default constructor initializes a model with 0 for minimum, 100 for maximum, and 0 for the value and extent properties. Another constructor allows specification of each of these initial values as int  parameters. As expected, this implementation does fire ChangeEvents whenever one of its properties changes.

13.1.3  JScrollBar

class javax.swing.JScrollBar

Scroll bars can be used to choose a new value from a specified interval by sliding a knob (often referred to as the thumb) between given maximum and minimum bounds, or by using small buttons at the ends of the component. The area not occupied by the thumb and buttons is known as the paging area, and this can also be used to change the current scrollbar value. The thumb represents the extent of this bounded-range component, and its value is stored in the visibleAmount property.

JScrollBar can be oriented horizontally or vertically, and its value increases to the right or upward respectively. To specify orientation, stored in the orientation property, we call the setOrientation() method and pass it one of the JScrollBar.HORIZONTAL or JScrollBar.VERTICAL constants.

Clicking on a button moves the thumb (and thus the value--recall that a bounded-range component's value lies at the beginning of the extent) by the value of JScrollBar's unitIncrement property. Similarly, clicking the paging area moves the thumb by the value of JScrollBar's blockIncrement property.

Note: It is common to match the visibleAmount property with the blockIncrement property. This is a simple way to visually signify to the user how much of the available range of data is currently visible.

UI Guideline : Usage of a Scrollbar Background

The Scrollbar is really a computer enhanced development from an original analog mechanical idea. Scrollbars are in some respects more advanced than Sliders (see section 13.1.4). The Thumb of the Scrollbar can very cleverly be used to show the current data as a percentage of a whole (as described in the Note above). If the scrollbar is placed onto an image and the thumb is approximately 50% of the total size, then the User is given a clear indication that the viewing area is roughly half of the total. The ability for the Thumb in a scrollbar to change size to accurately reflect this, is something which could not have been achieved with a mechanical device. Scrollbar is in this respect a very good example of taking a metaphor based on a mechanical device and enhancing it to improve usability.

Choosing Position

By far the best use of a scrollbar is position selection. They are in nature analog and to the viewer are giving only an approximate position. Position selection is how they are used throughout Swing inside a JScrollPane. Users have become used to this usage and its very natural. For most other occasions where you wish to use a sliding control for selection, a Slider is probably best.

As expected, JScrollBar uses a DefaultBoundedRangeModel by default. In addition to the ChangeEvents fired by this model, JScrollPane fires PropertyChangeEvents when its orientation, unitIncrement, or blockIncrement properties change state. JScrollPane also fires AdjustmentEvents whenever any of its bound properties change, or when any of it's model's properties change (this is done solely for backward compatibility with the AWT scrollbar class). Accordingly, JScrollPane provides methods to add and remove AdjustmentListeners (we don't need to provide methods for adding and removing PropertyChangeListeners because this functionality is inherited from JComponent).

Note: AdjustmentListeners receive AdjustmentEvents. Both are defined in java.awt.event--see API docs.

13.1.4  JSlider

class javax.swing.JSlider

Sliders can be used to choose a desirable numerical value from a specified interval by sliding a knob between given borders (using the mouse, arrow keys, or PageDown and PageUp). Sliders are very useful when we know in advance the range of input the user should be able to choose from.

JSlider supports horizontal and vertical orientations, and its orientation property can be set to one of JSlider.HORIZONTAL or JSlider.VERTICAL. The extent property specifies the number of values to skip forward/up or back/down when PageUp or PageDown is pressed, respectively. Tick marks can be used to denote value locations. Minor and major tick marks are supported, where major ticks are usually longer and spread farther apart than minor ticks. In the case where a major and minor tick fall on the same location, the major tick takes precedence and the minor tick will not be displayed. Spacing between minor tick marks is specified by the minorTickSpacing property, and spacing between major tick marks is specified by the majorTickSpacing property.

Note: The tick spacing properties specify the number of values to be skipped between each successive tick. Their names are somewhat misleading because they actually have nothing to do with the physical space (in pixels) between each tick. They would be more appropriately named "minorTickDisplayInterval" and "majorTickDisplayInterval. "

Setting either spacing property to 0 has a disabling effect, and the paintTicks property also provides a way of turning ticks on and off.

Note: The snapToTicks property is intended to only allow the slider knob to lie on a tick-marked value, however, this feature does not work as expected as of Java 2 FCS.

Major ticks can be annotated by components, and by default each of JSlider's major ticks are adorned with JLabel's denoting the integer tick value. We can turn on/off this functionality by changing the paintLabels property, and we can customize which components are used to annotate, and at what values they are placed, by passing a Dictionary of Integer/Component pairs to the setLabelTable() method. The createStandardLabels() method is used by default to set up JSlider with its JLabel's at each major tick value. This method returns a Hashtable (sub-class of Dictionary) which can then be assigned to JSlider using setLabelTable().

By default JSlider's values increment from left-to-right or bottom-to-top depending on whether horizontal or vertical orientation is used respectively. To reverse the direction of incrementation we can set the inverted property to true.

UI Guideline : Usage of a Slider

By origin a slider is an analog device. Sliders are really a close graphical and behavioural representation of a real world analog slider from for example, a hi-fi system or an older TV volume control. As such sliders are analog devices and are designed for use in determining an approximate or positional setting for something. Usually they rely on direct user feedback to help with the choice of position. With the TV volume control example, the volume would go up and down as the slider is moved and the User would stop moving it when the volume was at a comfortable level.

The Swing version of a slider is actually a digital device disguised as an analog one. Each tick of the slider is a digital increment. The slider can therefore be used to determine an accurate value providing some additional digital feedback is given for the User such as a numeric display of the absolute value or a scale along the side of the slider. Where accurate values are important, such as with a colour chooser, be sure to provide an absolute value as output along side the slider.

Feedback
Immediate feedback is important with sliders due to the analog nature of the device. Provide actual feedback such as the brightness of a picture which increases or decreases as the slider is moved or provide an absolute numeric value readout which can be observed to change as the slider is moved. Therefore, judicious use of the Change Event with a ChangeListener is important so that the feedback mechanism can be updated e.g. brightness or contrast in an image.

Movement
The two default orientations of Slider are conventions which date back to original analog electronic devices. When vertical, the down position is lower and you move it up to increase in value. When horizontal, left is lower and you move it right to increase in value. Users are likely to be very familiar with this convention. If you wish to switch it, then you should have a very very good reason for doing. We wouldn't recommend it!

Slider vs. Scrollbar

On the whole, use a Slider for choosing a value when the value needed is approximate and subjective such as color, volume, brightness and requires User feedback to make the subjective judgement. Use a scroll bar for positional choice, where the desired position is again approximate and judged relative to the whole.

The paintTrack property specifies whether the whole slider track is filled in or not. The Metal L&F UI delegate for JSlider pays attention to client property with key "JSlider.isFilled" and Boolean value. Adding this property to a JSlider's client properties hashtable (using putClientProperty()--see chapter 2) with a value of Boolean.TRUE, will fill in only the lower half of the slider track from the position of the knob. Note that this client property will have no effect if the paintTrack property is set to true, and will only work if the slider is using the Metal L&F UI delegate.

As expected, JSlider uses a DefaultBoundedRangeModel by default. In addition to the ChangeEvents fired by this model, JSlider fires PropertyChangeEvents when any of its properties desribed above change state. Unlike JScrollBar, this class provides the ability to add and remove ChangeListeners directly, vs. AdjustmentListeners.

13.1.5  JProgressBar

cass javax.swing.JProgressBar

Progress bars can be used to display how far or close a given numerical value is from the bounds of a specified interval. They are typically used to indicate progress during a certain lengthy job to provide simple feedback to the user showing that the job being monitored is alive and active. As with JScrollBar and JSlider, JProgressBar can be oriented horizontally or vertically. Note also that JProgressBar acts identically to JSlider with respect to incrementing: left-to-right in horizontal orientation, bottom-to-top in vertical orientation.

A JProgressBar is painted filled from the minimum value to its current value (with the exception of the Windows L&F, which paints a series of small rectangles). A percentage representing how much of a job has been completed can optionally by displayed in the center of JProgressBar. The string property represents the String to be painted (usually of the form XX%, where X is a digit), stringPainted specifies whether or not string should be painted, and percentComplete is a double between 0 and 1 specifying how much of the job has been completed so far.

Note: We normally do not need to take control of this rendering functionality, because by setting the string property to null, and the stringPainted property to true, the percentComplete property is convereted to the XX% form for us, and displayed in the progress bar.

JProgressBar's foreground and background can be assigned as any JComponent, however, the color used to render its status text is not directly modifiable. Instead this is handled by the UI delegate, and the easiest way to assign specific colors is to replace the appropriate UI resources in UIManager's defaults table (see chapter 21 for more about L&F customization).

The borderPainted property (defaults to true) specifies whether or not a border is rendered around JProgressBar. As expected, JProgressBar uses a DefaultBoundedRangeModel by default, and ChangeListeners can be added to receive ChangeEvents when any of JProgressBar's properties change state.

During a monitored operation we simply call setValue() on a JProgressBar and all updating is taken care of for us. Note that we must be careful to make this call in the event dispatching thread. Consider the following basic example, figure 13.1 illustrates:

Figure 13.1 A basic JProgressBar example showing custom colors and proper updating.

<<file figure13-1.gif>>

The Code: JProgressBarDemo.java

see \Chapter13\1

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.event.*;

public class JProgressBarDemo

  extends JFrame

{

  protected int m_min = 0;

  protected int m_max = 100;

  protected int m_counter = 0;

  protected JProgressBar jpb;

  public JProgressBarDemo()

  {

    super("JProgressBar Demo");

    setSize(300,50);

    UIManager.put("ProgressBar.selectionBackground", Color.black);

    UIManager.put("ProgressBar.selectionForeground", Color.white);

    UIManager.put("ProgressBar.foreground", new Color(8,32,128));

    jpb = new JProgressBar();

    jpb.setMinimum(m_min);

    jpb.setMaximum(m_max);

    jpb.setStringPainted(true);

    JButton start = new JButton("Start");

    start.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {

        Thread runner = new Thread() {

          public void run() {

            m_counter = m_min;

            while (m_counter <= m_max) {

              Runnable runme = new Runnable() {

                public void run() {

                  jpb.setValue(m_counter);

                }

              };

              SwingUtilities.invokeLater(runme);

              m_counter++;

              try {

                Thread.sleep(100);

              }

              catch (Exception ex) {}

            }

          }

        };

        runner.start();

      }

    });

    getContentPane().add(jpb, BorderLayout.CENTER);

    getContentPane().add(start, BorderLayout.WEST);

    WindowListener wndCloser = new WindowAdapter()

    {

      public void windowClosing(WindowEvent e)

      {

        System.exit(0);

      }

    };

    addWindowListener(wndCloser);

    setVisible(true);

  }

  public static void main(String[] args)

  {

    new JProgressBarDemo();

  }

}

Note: The JProgressBar UI delegate centers the progress text horizontally and vertically. However, its centering scheme enforces a certain amount of white space around the text and has undesirable effects when using thin progress bars. In order to fix this we can override BasicProgressBarUI's getStringPlacement() method (see API docs and BasicProgressBarUI.java source) to return the desired Point location where the text should be rendered.

UI Guideline : Usage of Progress Bar Long Operations

Progress Bars are commonly used as a fill in for operations which will take a long time. A long time in human interaction is often defined as around 1 second or longer. The progress bar is usually rendered inside a JOptionPane.

Special attention will need to be paid to the business logic code so that it is capable of notifying a Progress Bar of the progress of an operation.

Progress Bars are inherintly analog in nature. Analog data is particularly good for displaying change and for relative comparison. It is not good for exact measurement. The analog nature of a Progress Bar means that it is good for showing that something is happening and that progress is taking place. However, it is not good for giving an exact measure of completeness. If your problem domain requires the ability to measure exactly how complete a task is then you may to to supplement the progress bar with a digital reading of progress. This is common with Internet download dialogs and option panes.

A digital readout is particularly useful when the task to be completed will take a very long time. The progress bar may only be giving you a granularity of around 3% for each graphic. If it takes significantly long to progress by such a jump, say greater than 5 seconds, then the digital readout will give you a finer grained reading at 1% and will change approximately 3 times faster than your progress bar. The combination of the two helps to pass the time for the viewer and gives them the reassurance that something is happening whilst also giving them a very accurate view of progress. That is why the dual combination of digital and analog progress is popular with Internet download dialogs, as the task can be very long and cannot be determined by the application developer.

13.1.6  ProgressMonitor

class javax.swing.ProgressMonitor

The ProgressMonitor class is a convenient and intelligent means of deploying a dynamic progress bar in an application that performs time-consuming operations. This class is a direct sub-class of Object (thus it does not exist in the component hierarchy).

ProgressMonitor displays a JDialog containing a JOptionPane-style component. The note property represents a String that can change during the course of an operation and is displayed in a JLabel above the JProgressBar (if null is used this label is not displayed).

Two buttons, "OK" and "Cancel," are placed at the bottom and serve to dismiss the dialog and abort the operation respectively. The "OK " button simply hides the dialog. The "Cancel" button also hides the dialog, and sets the canceled property true, providing us with a way to test whether the user has canceled the operation or not. Since most time-consuming operations occur in loops, we can test this property during each iteration and abort if necessary.

The millisToDecideToPopup property is an int value specifying the number of milliseconds to wait before ProgressMonitor should determine whether to pop up a dialog (defaults to 500). This is used to allow a certain amount of time to pass before questioning whether the job is long enough to warrant popping up a dialog. The millisToPopup property is an int value specifying the minimum time a job must take in order to warrant popping up a dialog (defaults to 2000). If ProgressMonitor determines that the job will take less than millisToPopup milliseconds the dialog will not be shown.

The progress property is an int value specifying the current value of the JProgressBar. During an operation we are expected to update the note and progress in the event-dispatching thread (as demonstrated in the example above).

Warning: In light of theses properties we should only use a ProgressMonitor for simple, predictable jobs. ProgressMonitor bases the estimated time to completion on the value of its JProgressBar from start time to current evaluation time and assumes that a constant rate of progression will exist throughout the whole job. For transfering a single file this may be a fairly valid assumption. However, the rate of progress is highly dependant on how the job is constructed. If

Note: ProgressMonitor does not currently give us access to its JProgressBar component. We hope that in future implementations this will be accounted for, as this makes customization more difficult.

13.1.6  ProgressMonitorInputStream

class javax.swing.ProgressMonitorInputStream

This class extends java.io.FilterInputStream and contains a ProgressMonitor. When used in place of an InputStream, this class provides a very simple means of displaying job progress. This InputStream's overloaded read() methods read data and update the ProgressMonitor at the same time. We can access ProgressMonitorInputStream's ProgressMonitor with getProgressMonitor() but we cannot assign it a new one. (See the API docs for more about InputStreams.)



[ Return to Swing (Book) ]


Top 10 read Java Articles
 Get free "1000 Java Tips eBook"

 Java Calendar and Date: good to know facts and code examples

 Array vs ArrayList vs LinkedList vs Vector: an excellent overview and examples

 How can I convert any Java Object into byte array? And byte array to file object

 The Java Lesson 1: What is Java?

 How do I compare two dates and times, date between dates, time between times and

 Maven vs Ant or Ant vs Maven?

 How to open, read, write, close file(s) in Java? Examples on move, rename and de

 Java Array

 Java: JLabel font and color


[ More in News Section ]
Java Lessons

The Java Lesson 1:
What is Java?
The Java Lesson 2:
Anatomy of a simple Java program
The Java Lesson 3:
Identifiers and primitive data types
The Java Lesson 4:
Variables, constants, and literals
The Java Lesson 5:
Arithmetic operations, conversions, and casts
The Java Lesson 6:
Boolean expressions and operations
The Java Lesson 7:
Bitwise operations
The Java Lesson 8:
Flow control with if and else
The Java Lesson 9:
switch statements
The Java Lesson 10:
for, while, and do-while statements
The Java Lesson 11:
Using break and continue
The Java Lesson 12:
Class methods and how they are called
The Java Lesson 13:
Using the Math class
The Java Lesson 14:
Creating and calling custom class methods
The Java Lesson 15:
Overloading class methods
The Java Lesson 16:
An introduction to objects and object references
The Java Lesson 17:
The String class
The Java Lesson 18:
The StringBuffer class
The Java Lesson 19:
Initializing and processing arrays of primitives
The Java Lesson 20:
Initializing and processing arrays of objects
The Java Lesson 23:
Inheritance and overriding inherited methods
The Java Lesson 24:
abstract classes and polymorphism
The Java Lesson 25:
Interfaces, instanceof, and object conversion and casting
The Java Lesson 26:
Introduction to graphical programming and the java.awt packa
The Java Lesson 27:
The Component class
The Java Lesson 28:
Containers and simple layout managers
The Java Lesson 29:
The Color and Font classes
The Java Lesson 30:
Drawing geometric shapes
The Java Lesson 31:
Choice, List, and Checkbox controls
The Java Lesson 32:
Using the Scrollbar graphical control
The Java Lesson 33:
Menus and submenus
The Java Lesson 34:
An introduction to applets and the Applet class
The Java Lesson 35:
Essential HTML to launch an applet and pass it parameters
The Java Lesson 36:
Mouse event processing
Java Lesson 37:
Menus and submenus
Java Lesson 38:
The WindowListener interface and the WindowAdapter class
Java Lesson 39:
An introduction to GridBagLayout
Java Lesson 40:
An introduction to the Java Collections API
Java Lesson 41:
Exception handling with try, catch, and finally blocks
Java Lesson 42:
Claiming and throwing exceptions
Java Lesson 43:
Multithreading, the Thread class, and the Runnable interface
Java Lesson 44:
An introduction to I/O and the File and FileDialog classes
Java Lesson 45:
Low-level and high-level stream classes
Java Lesson 46:
Using the RandomAccessFile class
Java Lessons by
Joh Huhtala: Update

Latest articles
 Java Profiler JProbe to Resolve Performance Problems Faster

 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3


[ More in News Section ]


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy