Search code examples
javaswingjspinner

Get current range of a spinner?


My question is quite simple, unfortunately I can't find an answer. Basically, I have a Swing window, with 2 JSpinners. The second JSpinner has to define the high bound of the first JSpinner. So for example, if the user puts the value 4 on the second JSpinner, they mustn't be able to put a value higher than 4 in the first JSpinner. And if the value currently displayed in the first JSpinner is higher than 4 I'll set it to 4.

So I've built my two JSpinners with SpinnerNumberModel in the constructor to set the initial bounds:

// First spinner
SpinnerNumberModel spinnerLimits_sante = new SpinnerNumberModel(3, 0.25, 3, 0.25);
JSpinner spin_sante = new JSpinner(spinnerLimits_sante);

// Second spinner
JSpinner spin_sante_max = new JSpinner(spinnerLimits_sante_max);
SpinnerNumberModel spinnerLimits_sante_max = new SpinnerNumberModel(3, 3, 32767, 1);

To get the value of the second JSpinner when it changes, I thought about using a ChangeListener on it. So each time it changes, I can get the new value, recreate a SpinnerNumberModel object using the new bounds (the low-bound and the interval wouldn't change, however the high-bound will be updated and the value will be updated if it is higher than the high-bound).

ChangeListener listenerSanteMax = new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
        int newBound = spin_sante_max.getValue();
        // ...
    }
};
spin_sante_max.addChangeListener(listenerSanteMax);

Unfortunately this is where I'm stuck: JSpinner has no getter that would return a SpinnerNumberModel object nor its values. And even if there was one, it seems there's no setter either.

So, my question: Is it possible to dynamically change the range and value of a spinner?

Thanks in advance!


Solution

  • In the ChangeListener, instead of creating a new SpinnerNumberModel, just update the maximum value of the existing model. Here's two ways to do it.

    If the ChangeListener can see the spinner models, you can do the update directly.

    ChangeListener listenerSanteMax = new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            Number newMaximum = spinnerLimits_sante_max.getNumber().doubleValue();
            spinnerLimits_sante.setMaximum((Comparable) newMaximum);
        }
    };
    

    If the ChangeListener can't see the spinner models, you can do a cast. JSpinner has a getModel() method the returns a SpinnerModel. You can cast it to a SpinnerNumberModel, but you should use instanceof to check that the cast will work.

    ChangeListener listenerSanteMax = new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent e) {
            Object source = e.getSource();
            if (source instanceof JSpinner) {
                JSpinner spinner = (JSpinner) source;
                SpinnerModel sm = spinner.getModel();
                if (sm instanceof SpinnerNumberModel) {
                    SpinnerNumberModel model = (SpinnerNumberModel) sm;
                    Number newMaximum = model.getNumber().doubleValue();
                    spinnerLimits_sante.setMaximum((Comparable) newMaximum);
                }
            }
        }
    };
    

    In either case, newMaximum is a Number, and all subclasses supported by SpinnerNumberModel are Comparable.