JSpinner NULL értékkel

    A JSpinner, pontosbban a JSpinner modellek komoly fogyatékossága, hogy nem képesek kezelni a null értékeket és az üres értéket. Az egyik lehetőség, hogy a fejlesztő megírja a saját modelljét vagy származtat a megévő modellekből, ami nem egy hálás feladat, netán keres az Interneten (én nem találtam).

    De van egy egyszerű megoldás a problémára: közvetlenül a JSpinner editor szöveges mezőjét is lehet használni a null érték tárolására: ha null-t állítunk be, üres String-re álíltjuk, lekérdezésnél pedig megvizsgáljuk, hogy üres String-e az értéke, és ha igen, akkor az null értéket jelent.

    Ehhez két dolog kell:

    1. Null érték tárolására alkalmas modell
    2. Üres mező kezelésére alkalmas editor

    Null érték tárolására alkalmas modell

    public class ExtraSpinnerNumberModel extends SpinnerNumberModel {
    
        private boolean nullValue = false;
    
        public ExtraSpinnerNumberModel(Number value, Comparable minimum, Comparable maximum, Number stepSize) {
            super(value, minimum, maximum, stepSize);
        }
    
        public ExtraSpinnerNumberModel(int value, int minimum, int maximum, int stepSize) {
            super(value, minimum, maximum, stepSize);
        }
    
        public ExtraSpinnerNumberModel(double value, double minimum, double maximum, double stepSize) {
            super(value, minimum, maximum, stepSize);
        }
    
        public ExtraSpinnerNumberModel() {
        }
    
        @Override
        public Object getValue() {
            return nullValue ? null : super.getValue();
        }
    
        @Override
        public void setValue(Object value) {
            boolean wasNull = nullValue;
            nullValue = value == null;
            if (!nullValue) {
                super.setValue(value);
            } else if (!wasNull) {
                fireStateChanged();
            }
        }
    
        @Override
        public Object getNextValue() {
            return nullValue ? null : super.getNextValue();
        }
    
        @Override
        public Object getPreviousValue() {
            return nullValue ? null : super.getPreviousValue();
        }
    }

    Üres mező kezelésére alkalmas editor

    public class ExtraNumberEditor extends JSpinner.NumberEditor {
    
        public ExtraNumberEditor(JSpinner spinner) {
            super(spinner);
            NumberEditorFormatter nef = new NumberEditorFormatter();
            SpinnerModel model = spinner.getModel();
            if (model instanceof SpinnerNumberModel) {
                SpinnerNumberModel numberModel = (SpinnerNumberModel) model;
                nef.setMinimum(numberModel.getMinimum());
                nef.setMaximum(numberModel.getMaximum());
            }
            getTextField().setFormatterFactory(new DefaultFormatterFactory(nef));
        }
    
        public ExtraNumberEditor(JSpinner spinner, String decimalFormatPattern) {
            super(spinner);
            NumberEditorFormatter nef
                = new NumberEditorFormatter(decimalFormatPattern);
            SpinnerModel model = spinner.getModel();
            if (model instanceof SpinnerNumberModel) {
                SpinnerNumberModel numberModel = (SpinnerNumberModel) model;
                nef.setMinimum(numberModel.getMinimum());
                nef.setMaximum(numberModel.getMaximum());
            }
            getTextField().setFormatterFactory(new DefaultFormatterFactory(nef));
        }
    
        static class NumberEditorFormatter
            extends NumberFormatter {
    
            public NumberEditorFormatter() {
                super(NumberFormat.getInstance());
            }
    
            public NumberEditorFormatter(String decimalFormatPattern) {
                super(new DecimalFormat(decimalFormatPattern));
            }
    
            @Override
            public Object stringToValue(String text) throws ParseException {
                if (text.isEmpty()) {
                    return null;
                }
                return super.stringToValue(text);
            }
    
            @Override
            public String valueToString(Object value) throws ParseException {
                if (value == null) {
                    return "";
                }
                return super.valueToString(value);
            }
    
        }
    }

    Modell és editor beállítása

    spinner.setModel(new ExtraSpinnerNumberModel(Double.valueOf(0.0), null, null, Double.valueOf(1.0)));
    spinner.setEditor(new ExtraNumberEditor(spinner));
    Tags: ,