Question

It is required to create a JSpinner with following features.

  • Range should be 0 to 1000 with 10 increment.
  • Display format should be 4 digits. (ex : 10 -> 0010)
  • It must allow user to enter the values manually.
  • It should not allow characters other than digits.
  • It should not allow enter values having more than 3 digits.

This is my current implementation :

spinnerUpDown.setModel(new SpinnerNumberModel(0,0,1000,10));
spinnerUpDown.setEditor(new JSpinner.NumberEditor(spinnerUpDown,"0000"));
JFormattedTextField txt = ((JSpinner.NumberEditor) spinnerUpDown.getEditor()).getTextField();
((NumberFormatter) txt.getFormatter()).setAllowsInvalid(false);

Problem with that implementation is, it will not allow user to manually enter a value.

If I remove the line :

((NumberFormatter) txt.getFormatter()).setAllowsInvalid(false);

It will allow me to enter values manually, but it allows to enter letters also.

Any suggestions to over come this problem. Thank you!!

Was it helpful?

Solution

JSpinner typically uses a JTextComponent for its editor. You could get the editor and apply a DocumentFilter to it.

This will allow you to filter the text coming into the document.

Check these, often cited, examples

Example

JFormattedTextField is installing it's own DocumentFilter. You can overcome this by providing your own PlainDocument that returns it's own filter

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
import javax.swing.text.PlainDocument;

public class TestSpinner01 {

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

    public TestSpinner01() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JSpinner spinnerUpDown = new JSpinner();
                spinnerUpDown.setModel(new SpinnerNumberModel(0, 0, 1000, 10));
                spinnerUpDown.setEditor(new JSpinner.NumberEditor(spinnerUpDown, "0000"));
                System.out.println(spinnerUpDown.getEditor());


                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(spinnerUpDown);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                PlainDocument doc = new PlainDocument() {
                    private TestFilter filter;
                    @Override
                    public DocumentFilter getDocumentFilter() {
                        if (filter == null) {
                            filter = new TestFilter();
                        }
                        return filter;
                    }

                };

                JTextComponent txt = ((JSpinner.DefaultEditor) spinnerUpDown.getEditor()).getTextField();
                txt.setDocument(doc);
            }
        });
    }

    public class TestFilter extends DocumentFilter {

        @Override
        public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException {
            System.out.println("remove");
            super.remove(fb, offset, length);
        }

        @Override
        public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
            System.out.println("insert");
            super.insertString(fb, offset, string, attr);
        }

        @Override
        public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            System.out.println("Replace...");
            super.replace(fb, offset, length, text, attrs);
        }
    }
}

Strangely enough, you example code worked well for me, but the problem I actually had was to do with the formatter

OTHER TIPS

Register KeyListener for JFormattedTextField. In the keyPressed() method, if the typed key is non-numeric character, then you can set the character of KeyEvent to empty string. so nothing will be appearing in the JFormattedTextField

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top