Using JSpinner in Java Swing tutorial

JSpinner is a Swing component in Java used for selecting a value from a sequence of values. It is often used when a user needs to input numerical values, dates, or other incremental data, providing a compact and user-friendly interface.

A JSpinner consists of a text field with up and down arrows, allowing users to increase or decrease the value in the spinner.

In this tutorial, we'll cover the following topics:

1. Creating a Basic JSpinner

The simplest way to create a JSpinner is by using its default constructor, which allows you to spin through a sequence of integer values.

Example 1: Basic JSpinner

import javax.swing.*;

public class JSpinnerExample1 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Basic JSpinner Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a basic JSpinner
            JSpinner spinner = new JSpinner();

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

A JSpinner is created using the default constructor, which provides a spinner with integer values starting at 0.
The spinner is added to the JFrame and displayed.

2. Using Spinner Models

JSpinner uses a model to define the type of data it can spin through. There are several built-in models you can use:

SpinnerNumberModel: For numerical values.
SpinnerListModel: For a list of predefined values.
SpinnerDateModel: For date values.

Example 2: Using SpinnerNumberModel

import javax.swing.*;

public class JSpinnerExample2 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Number Spinner Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a number model (initial value 5, min 0, max 10, step 1)
            SpinnerNumberModel numberModel = new SpinnerNumberModel(5, 0, 10, 1);
            JSpinner spinner = new JSpinner(numberModel);

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

SpinnerNumberModel is used to define the spinner's numeric range (minimum, maximum, and step size).
The initial value is set to 5, the range is from 0 to 10, and the spinner increments or decrements by 1 with each click.

Example 3: Using SpinnerListModel

import javax.swing.*;

public class JSpinnerExample3 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("List Spinner Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a list model
            String[] fruits = {"Apple", "Banana", "Orange", "Grapes"};
            SpinnerListModel listModel = new SpinnerListModel(fruits);
            JSpinner spinner = new JSpinner(listModel);

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

SpinnerListModel is used to define a spinner that cycles through a list of predefined values (in this case, a list of fruits).
The spinner allows users to select one of the items from the list.

Example 4: Using SpinnerDateModel

import javax.swing.*;
import java.util.Date;

public class JSpinnerExample4 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Date Spinner Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a date model
            SpinnerDateModel dateModel = new SpinnerDateModel(new Date(), null, null, java.util.Calendar.DAY_OF_MONTH);
            JSpinner spinner = new JSpinner(dateModel);

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

SpinnerDateModel is used to create a spinner that allows users to select dates. It uses java.util.Calendar constants to define the unit of increment (in this case, days).
You can increment or decrement the date using the spinner.

3. Customizing the Appearance of JSpinner

You can customize the appearance of JSpinner by setting its editor component, which determines how the value is displayed and edited.

Example 5: Customizing JSpinner with a Number Format

import javax.swing.*;
import javax.swing.text.NumberFormatter;
import java.text.NumberFormat;

public class JSpinnerExample5 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Custom JSpinner Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a number model
            SpinnerNumberModel numberModel = new SpinnerNumberModel(50, 0, 100, 5);
            JSpinner spinner = new JSpinner(numberModel);

            // Customize the editor to format numbers with a comma separator
            JFormattedTextField txt = ((JSpinner.NumberEditor) spinner.getEditor()).getTextField();
            NumberFormatter formatter = (NumberFormatter) txt.getFormatter();
            formatter.setFormat(NumberFormat.getIntegerInstance());

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

We customize the spinner's editor to display numbers with a comma separator by modifying the NumberFormatter for the spinner's text field.
The NumberFormatter is used to format the numbers (e.g., 1,000 instead of 1000).

4. Handling Value Changes in JSpinner

You can listen for changes in the spinner's value using the ChangeListener. This allows you to perform actions when the spinner's value is updated.

Example 6: Handling Value Changes in JSpinner

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class JSpinnerExample6 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("JSpinner Change Listener");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a number model
            JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));

            // Label to display the current value
            JLabel valueLabel = new JLabel("Current Value: 0");

            // Add a change listener to the spinner
            spinner.addChangeListener(new ChangeListener() {
                @Override
                public void stateChanged(ChangeEvent e) {
                    // Update the label when the spinner value changes
                    int value = (Integer) spinner.getValue();
                    valueLabel.setText("Current Value: " + value);
                }
            });

            frame.setLayout(new java.awt.FlowLayout());
            frame.add(spinner);
            frame.add(valueLabel);
            frame.setVisible(true);
        });
    }
}

Explanation:

A ChangeListener is added to the JSpinner to listen for value changes.
Each time the spinner's value changes, the label is updated to display the current value.

5. JSpinner with Custom Step Size

Sometimes, you may want a spinner that steps through values differently. For example, you might want a spinner that increments by 0.5 instead of 1.

Example 7: Spinner with Custom Step Size

import javax.swing.*;

public class JSpinnerExample7 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Custom Step Size JSpinner");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a number model that steps by 0.5
            SpinnerNumberModel numberModel = new SpinnerNumberModel(0.0, 0.0, 10.0, 0.5);
            JSpinner spinner = new JSpinner(numberModel);

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

The spinner steps through values with a custom step size of 0.5 (increments and decrements by 0.5 each time).

6. Creating a JSpinner with Custom Values

You can create a JSpinner with any custom values, such as predefined names, days of the week, or specific text values.

Example 8: Spinner with Custom String Values

import javax.swing.*;

public class JSpinnerExample8 {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Custom Values JSpinner");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(300, 150);

            // Create a spinner with a list model containing custom string values
            String[] customValues = {"Low", "Medium", "High"};
            SpinnerListModel listModel = new SpinnerListModel(customValues);
            JSpinner spinner = new JSpinner(listModel);

            frame.add(spinner);
            frame.setVisible(true);
        });
    }
}

Explanation:

The SpinnerListModel is used to create a spinner with a set of predefined string values (“Low”, “Medium”, “High”).

Conclusion

JSpinner is a flexible and powerful Swing component that allows users to select values by incrementing or decrementing them.

It can handle a variety of data types, including numbers, lists, and dates, and it supports customization of both its appearance and functionality.

By using ChangeListener, you can easily handle value changes and perform actions based on user input.

Summary of Key Points:

Basic JSpinner: Use the default constructor to create a simple integer spinner.
Spinner Models: Use SpinnerNumberModel, SpinnerListModel, and SpinnerDateModel to customize the data in the spinner.
Custom Editors: Modify the appearance of the spinner's editor to format numbers, dates, or other values.
ChangeListener: Listen for value changes using ChangeListener to update other components or perform tasks.
Custom Step Sizes: Define custom step sizes for number-based spinners.
Custom Values: Use SpinnerListModel to create a spinner with predefined custom values.

Related posts

Tutorial on Java GroupLayout in Swing

Tutorial on Java GridBagLayout in Swing

Tutorial on Java GridLayout in Swing