JSlider Tutorial


Summary:

The function of many UI components is to put constraints on the type of input a user can provide software.  Where buttons constrain response data to binary yes or no (selected or not selected) replies, and text field components allow the user to enter nearly any data he or she pleases, sliders are make it possible to constrain the user’s choice of values within a pair of numerical boundary values and to a specific precision. Sliders are appropriate for entering numerical values between a set minimum and maximum (such as a security level or simulated thermostat setting) and when there are a finite number of options to choose from (like low/medium/high/maximum security, or any whole degree between 50°F and 80°F degrees).

Where to Find It:

        The JSlider can be found in javax.swing.JSlider in the javax.swing package.
 
               Import into your projects using the command:
 
        import javax.swing.JSlider;

The Basics:

JSlider widgets can be added to your Java Swing GUIs like any other widget type.  In the following example, a simple JSlider and JLabel are created and added to the JSliderDemo’s content pane.  The JSlider contructor, “JSlider slider = new JSlider(50, 90, 75)”, creates a new JSlider object with default settings and values ranging from a minimum of 50 (the first parameter), a maximum of 90 (the second parameter) and a starting value of 75 (the third parameter).  Try running the following Java program to see a simple JSlider in action.

import java.util.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.border.*;

 

public class JSliderDemo extends JFrame {

   

    /** Creates a new instance of JSliderDemo */

    public JSliderDemo() {

       

        super("A JSlider Demo Application");

       

        JSlider slider = new JSlider(50, 90, 75);

        JLabel label = new JLabel("Thermostat Setting ” +

                       “(degrees Fahrenheit)");

       

        slider.setPaintTicks(true);

        slider.setMajorTickSpacing(10);

        slider.setPaintLabels( true );

       

        getContentPane().setLayout(new FlowLayout());

        getContentPane().add(slider);

        getContentPane().add(label);

    }

   

    public static void main(String args[]) {

        JSliderDemo demo = new JSliderDemo();

        demo.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {

                System.exit(0);

            }

        });

        demo.setSize(250, 120);

        demo.show();

    }

}

Running this code should create something like this:

Figure 1: Simple JSlider Demo

Note that the default value for the JSlider is 75, as specified in the JSlider constructor.  The slider can be selected with the mouse and dragged to any other value on the slider rail (from 50 to 90 inclusive).

Also note the options set in the JSliderDemo constructor method:

        slider.setPaintTicks(true);

        slider.setMajorTickSpacing(10);

        slider.setPaintLabels( true );

The “setPaintTicks” method toggles the visibility of the small vertical lines immediately above each number in the application (See Figure 1).  These “ticks” are optional, but can be a helpful user reference when trying to select a particular value.  Note that the default value for this option is “false”, so by default a newly created JSlider will not display these ticks.  Their visibility must be explicitly set.

The “setMajorTickSpacing” method sets the numerical interval between the labeled values on the JSlider rail (the numbers in bold in Figure 1).  Since this value is currently set to “10”, the labels on the slider rail are labeled every ten values (hence the labels at 50, 60, 70, and so on).  Setting this value to “5” would generate labels every five values (50, 55, 60, 65, and so on), and setting it higher to “20” would create labels ever 20 values (at 50, 70, and 90 only).  Setting this value higher reduces the number of reference labels on the slider rail, while lowering it clutters the slider rail with additional labels.  The ideal number of labels is left to the programmer to decide.

The “setPaintLabels” method is very important: by default the JSlider will not paint any labels on the slider rail.  In order to include labeled values in your JSlider, you must define the frequency of the labels using the “setMajorTickSpacing” method above, and explicitly set the “setPaintLabels” value to true, as in the example.

Now you know enough to create a simple JSlider and include it in your Swing GUI.  However, by itself, the slider isn’t terribly useful.  By using Listeners, you can utilize the dynamic value of the slider in your application.

ChangeListeners wait for their widget’s value to change, and send notification of the change to the “StateChanged” method implemented inside the ChangeListener.  From there, you can find what changed, and send that information to other areas of your program.  In the case of JSliders, whenever the slider is moved to a different value, a ChangeEvent is sent to all ChangeListeners added to that JSlider.  An example of this process is described in the code below:

import java.util.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.border.*;

import javax.swing.event .ChangeListener;

import javax.swing.event.ChangeEvent;

 

public class JSliderDemo extends JFrame {

   

    JSlider slider;

    JLabel label;

    JLabel warning;

   

    public JSliderDemo() {

       

        super("A JSlider Demo Application");

       

        slider = new JSlider(50, 90, 75);

        slider.addChangeListener(new DemoSliderListener());

        label = new JLabel("Thermostat Setting (degrees Fahrenheit)");

        warning = new JLabel();

               

        slider.setPaintTicks(true);

        slider.setMajorTickSpacing(10);

        slider.setPaintLabels( true );

       

        getContentPane().setLayout(new FlowLayout());

        getContentPane().add(slider);

        getContentPane().add(label);

        getContentPane().add(warning);

    }

   

    public void evaluateTemperature(int temp) {

       

        if (temp < 60) {

            // If temperature is too cold, say so.

            warning.setText(temp + " degrees is too cold!");

            warning.setForeground(Color.blue);

        } else if (temp > 80) {

            // If temperature is too hot, say so.

            warning.setText(temp + " degrees is too hot!");

            warning.setForeground(Color.red);

        } else {

            // Otherwise, the temperature is fine.

            warning.setText(temp + " degrees is just right!");

            warning.setForeground(Color.black);

        }

    }

   

    class DemoSliderListener implements ChangeListener {

        public void stateChanged(ChangeEvent e) {

            JSlider sourceSlider = (JSlider)e.getSource();

            int temperature = (int)sourceSlider.getValue();

            evaluateTemperature(temperature);

        }

    }

   

    public static void main(String args[]) {

        JSliderDemo demo = new JSliderDemo();

        demo.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {

                System.exit(0);

            }

        });

        demo.setSize(250, 120);

        demo.show();

    }

}

In this example, built upon the first JSliderDemo, an additional “warning” label has been added to the window.  This label is designed to be updated (via the “evaluateTemperature” method) to comment on the temperature the user has selected.  Run the above example code to see how Listeners can be used with JSliders.

Figure 2: JSlider Demo with Listener Updates

Customization:

The orientation of JSliders can be customized using the “setOrientation” method and the orientation constants of the JSlider class (JSlider.VERTICAL, JSlider.HORIZONTAL).  It is sometimes desirable to implement a slider that moves up and down rather than the default left and right placement, especially when GUI real estate and layout is a concern.

The JSlider value scale can be inverted using the “setInverted(boolean)” method.  If a JSlider is inverted, the minimum and maximum values are drawn in reverse order than the JSlider default.  For example, setting the JSliderDemo’s inversion property to true would draw a JSlider listing temperature values from 90 down to 50 instead of the other way around.

Major tick spacing was covered in the Basics section of this tutorial.  The novice user should also be aware that minor tick spacing can be implemented in much the same way.  A minor tick looks like a major tick in that it creates a visual reference for the user to a possible value to select.  However, minor ticks are smaller than major ticks, and are not labeled with a number, as major ticks are.  Minor ticks can be implemented by adding the line:

        slider.setMinorTickSpacing(5);

immediately after the major tick spacing method in the example code.  This would produce a JSlider that looks like this:

Figure 3: JSlider with Minor Ticks Displayed

 

Finally, JSliders can also be customized to “Snap to” tick marks on the rail (whether or not they are visibly displayed).  By default, a user can drag the slider to any location on the rail, regardless to whether or not that exact position on the rail maps to a specific value or not.  In this instance, the JSlider assumes that the user has selected the nearest value to that location (rounded to the nearest whole value).  Utilizing the “snap to” option using the “setSnapToTicks” method causes the slider to visibly jump to its nearest value on the rail, preventing the user from dropping the slider on an “in-between” value.  This can be useful if you are implementing a JSlider with very few selectable values on it, and you do not wish for the user to have any doubt about exactly which value is currently selected.

Best Practices:

JSliders are best used where the user is required to select one of a number of possible response values, and the precision of the response is already known by the programmer.  The user is prevented from entering invalid responses, and guided toward one of several or many acceptable candidate answer values.

In cases where the number of selectable values is very small, one should consider radio buttons instead of sliders, especially if the response data is not easily ordered in a “range” of options (high-to-low, most-to-least, etc.).

Limitations:

JSliders are excellent at pinpointing a response value from a choice of many, but weak at indicating a deliberate value submission as opposed to a temporary value selection.  For this reason, JSliders are best used alongside other components that can elaborate on the meaning of the selected value (text fields, labels, and so on), and provide some means (other than ChangeListeners) to indicate that the user is done altering the value of the slider, and wishes to proceed with the selected value (buttons).

Things to Watch Out for When Including JSliders:

Utilizing a JSlider’s features requires a deliberate setting of its internal properties!  Often, slider features default to “off”, leaving your JSlider very minimal upon initial creation.  Adding tick marks and label values has to be done explicitly by the programmer, as the JSlider implementation will assume they are absent unless he or she specifies they are to be included!

The default orientation of a JSlider is HORIZONTAL.  To create a VERTICAL JSlider, the orientation property must be set in the constructor, or using the “setOrientation” method.  See the JSlider javadoc for more details.

References:

The JSlider javadoc directly from the Sun website.  Contains a detailed view of the contents of the JSlider class.

 

Other Helpful Resources:

A comprehensive JSlider tutorial from the Sun website.