JSpinner with SpinnerNumberModel: Is there a validation of entered numbers?

198 Views Asked by At

The goal is to have a JSpinner like this with:

SpinnerNumberModel(1650, 1650, 2100, 10);
setEditable(true);
setFocusable(true);

It should also only accept numeric values ​​in the range 1650-2100. If the value is not in this range, set the default value (1650). At the moment, my code only allows me to enter 4 digits, but they are out of range.I have read a lot of similar questions, but I have not found a topic anywhere with a limitation of the input number in the Jspinner.

public class MySpinner extends JSpinner {
    int defValue;
    int minimum;
    int maximum;
    int stepSize;

    public MySpinner(int defValue, int minimum, int maximum, int stepSize) {
        this.defValue = defValue; //1650
        this.minimum = minimum;   //1650
        this.maximum = maximum;   //2100
        this.stepSize = stepSize; //10
        SpinnerNumberModel spinnerNumberModel = new SpinnerNumberModel(defValue, minimum, maximum, stepSize);
        setModel(spinnerNumberModel);
        setBorder(new EmptyBorder(0, 0, 0, 0));

        JSpinner.NumberEditor numberEditor = ((JSpinner.NumberEditor) this.getEditor());
        numberEditor.getTextField().setEnabled(true);
        numberEditor.getTextField().setEditable(true);
        numberEditor.getFormat().setMaximumFractionDigits(4);

        JFormattedTextField textField = numberEditor.getTextField();
        ((NumberFormatter) textField.getFormatter()).setAllowsInvalid(false);
        NumberFormatter formatter = (NumberFormatter) textField.getFormatter();
        DecimalFormat decimalFormat = new DecimalFormat("0");
        formatter.setFormat(decimalFormat);

        final Document jsDoc = numberEditor.getTextField().getDocument();
        if (jsDoc instanceof PlainDocument) {
            AbstractDocument doc = new PlainDocument() {
                private static final long serialVersionUID = 1L;

                @Override
                public void setDocumentFilter(DocumentFilter filter) {
                    if (filter instanceof MyDocumentFilter) {
                        super.setDocumentFilter(filter);
                    }
                }
            };
            doc.setDocumentFilter(new MyDocumentFilter());
            numberEditor.getTextField().setDocument(doc);
        }
    }

    public static class MyDocumentFilter extends DocumentFilter {

        @Override
        public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
            if (stringContainsOnlyDigits(string)) {
                super.insertString(fb, offset, string, attr);
            }
        }

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

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            int currentLength = fb.getDocument().getLength();
            int overLimit = (currentLength + text.length()) - 4 - length;
            if (overLimit > 0) {
                text = text.substring(0, text.length() - overLimit);
            }
            if (stringContainsOnlyDigits(text)) {
                super.replace(fb, offset, length, text, attrs);
            }
        }

        private boolean stringContainsOnlyDigits(String text) {

            for (int i = 0; i < text.length(); i++) {
                if (!Character.isDigit(text.charAt(i))) {
                    return false;
                }
            }
            return true;
        }
    }
}

Perhaps there is a lot of unnecessary stuff in my code. I would be glad to any advice. Thanks in advance.

0

There are 0 best solutions below