JSpinner and JSlider of Swing

Hello everyone. This page is an English translation of a Japanese page. (The original Japanese has been slightly rewritten to make it easier to translate into English.)

This time, we dealt with JSpinner and JSlider in Swing.

JSpinner and JSlider are used to ask the user to select a value from a sequence of values. JSpinner displays up and down buttons for the user to change the value. JSlider displays a slider for the user to change the value. By sliding the control knob, the user can change the value.

We will use the following program as a template.

Source
import javax.swing.JFrame;

public class Test extends JFrame {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(350, 250);

        init();

        setVisible(true);

    }

    private void init() {
        // installation process
    }

}

JSpinner

JSpinner and SpinnerModel

In JSpinner, the following constructors are provided.

  • JSpinner()
  • JSpinner(SpinnerModel model)

The second constructor argument is the SpinnerModel interface. This interface manages the range of values and the initial value.

The first constructor has no arguments. Internally, an instance of SpinnerNumberModel will be created. This class is an implementation class of the SpinnerModel interface. In the created instance, the initial value is set to 0, and the minimum and maximum values are set to unrestricted. In this constructor, it seems to be normal to specify an instance of the SpinnerNumberModel class as an argument.

There are several constructors, but we will use the following one.

  • SpinnerNumberModel(int value, int minimum, int maximum, int stepSize)

In fact, we used the following.

Source
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

public class Test2 extends JFrame {

    public static void main(String[] args) {
        new Test2();
    }

    public Test2() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(350, 250);

        init();

        setVisible(true);

    }

    private void init() {
        setLayout(new FlowLayout());

        JSpinner spinner1 = new JSpinner();
        add(spinner1);

        JSpinner spinner2 = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
        add(spinner2);

        JSpinner spinner3 = new JSpinner(new SpinnerNumberModel(0, -10000, 10, 1));
        add(spinner3);
    }

}
JSpinner001.png

In the above, we have set up a FlowLayout object as the layout manager.

The width of each JSpinner object is determined from the minimum and maximum values set in the SpinnerNumberModel. For the object stored in the variable spinner1, there is no restriction on the value, but the number of digits displayed has been reduced to a single digit. So it might be better to use an instance of SpinnerNumberModel to explicitly determine the minimum and maximum values. However, if BorderLayout is set in the layout manager, the width of the object will automatically increase.

ChangeListener

By using the addChangeListener method, you can add a listener to JSpinner. The argument of this method is the ChangeListener interface. This interface has only the stateChanged method. This method is called every time the value of JSpinner is changed.

The following is an example implementation.

Source
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

public class Test3 extends JFrame {

    public static void main(String[] args) {
        new Test3();
    }

    public Test3() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(350, 250);

        init();

        setVisible(true);

    }

    private void init() {
        setLayout(new FlowLayout());

        JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
        add(spinner);

        spinner.addChangeListener(event -> {
            System.out.println("current value: " + spinner.getValue());
        });
    }

}

When the above program is executed, JSpinner is placed in the window. When the top button is clicked, “current value: 1" is displayed in the console.

JSlider

Constructor and BoundedRangeModel

Internally in JSlider, the BoundedRangeModel interface handles the range of values. There is a constructor, for example JSlider(BoundedRangeModel brm). There are other constructors that can be used without being aware of the BoundedRangeModel.

In this case, we used the following constructor.

  • JSlider()
  • JSlider(int min, int max, int value)

There are more constructors than the above, although we will not use them this time. Also, the implementation class of the BoundedRangeModel interface used seems to be DefaultBoundedRangeModel.

In the following sample, three sliders will be placed.

Source
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JSlider;

public class Test4 extends JFrame {

    public static void main(String[] args) {
        new Test4();
    }

    public Test4() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(350, 250);

        init();

        setVisible(true);

    }

    private void init() {
        setLayout(new FlowLayout());

        JSlider slider1 = new JSlider();
        add(slider1);

        JSlider slider2 = new JSlider(0, 10, 2);
        add(slider2);

        JSlider slider3 = new JSlider(-1000, 0, -100);
        add(slider3);
    }
}
JSlider001.png

The JSlider() method generates a horizontal slider with a range of 0 to 100 and an initial value of 50.

The JSlider(int min, int max, int value) method creates a horizontal slider with the minimum, maximum, and initial values set in each argument. Negative numbers can also be specified.

If there is any contradiction in the combination of numbers specified in the above arguments, IllegalArgumentException will be thrown. In that case, the following error message will be output.

  • java.lang.IllegalArgumentException: invalid range properties

For example, the above error will occur for the argument combination “new JSlider(0, 10, -2)".

addChangeListener and JLabel

There are several ways to display the slider value, for example using JLabel. This is how to set the slider value to the label. The listener for when the value of the slider is changed can be set with addChangeListener.

In the following, when the value of the slider is changed, the value is output to JLabel.

Source
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;

public class Test5 extends JFrame {

    public static void main(String[] args) {
        new Test5();
    }

    public Test5() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(350, 250);

        init();

        setVisible(true);

    }

    private void init() {
        setLayout(new FlowLayout());

        JSlider slider = new JSlider();
        add(slider);

        JLabel label = new JLabel(String.valueOf(slider.getValue()));
        add(label);

        slider.addChangeListener(event -> {
            label.setText(String.valueOf(slider.getValue()));
        });
    }

}
JSlider002.png

Since the constructor JSlider() is used to create the instance, the initial value is 50. Initially, the label will show 50. Dragging and moving the slider knob with the mouse will change the display of the label.

Scales and labels

Scales can be added to the slider. To do so, use the following method.

  • void setPaintTicks(boolean b)
  • void setMinorTickSpacing(int n)
  • void setMajorTickSpacing(int n)

First, specify true as the argument of the setPaintTicks method, and set the minor and major ticks using the setMinorTickSpacing and setMajorTickSpacing methods. The ticks will not be displayed just by executing setPaintTicks(true).

If you want to add more labels, write setPaintLabels(true). By default, labels are displayed according to the large scale. To specify the labels, use the void setLabelTable(Dictionary labels) method. Since the Dictionary class contains abstract methods, we actually use its subclass Hashtable. Here, the key/value combination is the Integer class and the java.swing.JComponent class.

The following is an example of the configuration.

Source
import java.awt.FlowLayout;
import java.util.Dictionary;
import java.util.Hashtable;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSlider;

public class Test6 extends JFrame {

    public static void main(String[] args) {
        new Test6();
    }

    public Test6() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(350, 250);

        init();

        setVisible(true);

    }

    private void init() {
        setLayout(new FlowLayout());

        JSlider slider1 = new JSlider();
        add(slider1);

        slider1.setPaintTicks(true);
        slider1.setMinorTickSpacing(10);
        slider1.setMajorTickSpacing(20);

        JSlider slider2 = new JSlider();
        add(slider2);

        slider2.setPaintTicks(true);
        slider2.setMinorTickSpacing(10);
        slider2.setMajorTickSpacing(20);
        slider2.setPaintLabels(true);


        JSlider slider3 = new JSlider();
        add(slider3);

        slider3.setPaintTicks(true);
        slider3.setMinorTickSpacing(10);
        slider3.setMajorTickSpacing(20);

        Dictionary<Integer, JComponent> dictionary = new Hashtable<>();
        dictionary.put(0, new JLabel("min"));
        dictionary.put(50, new JLabel("middle"));
        dictionary.put(100, new JLabel("max"));

        slider3.setPaintLabels(true);
        slider3.setLabelTable(dictionary);
    }
}
JSlider003.png

In slider1, we set the scales. We set 10 on the small scale and 20 on the large scale. In slider2, we further displayed the labels. Since this is the default setting, the label will be displayed according to the large scale. In slider3, we labeled the ticks 0, 50, and 100. We used JLabel, which is a subclass of JComponent. Here, we used the constructor JLabel(String text), but you can add an image by using JLabel(Icon image).

That’s all. I hope this is helpful to you.

Articles next and previous in the same category