Search code examples
javaswingjspinnerchangelistener

How does JSpinner stateChanged works?


Why does the code enters twice in the change event of the JSpinner?

private javax.swing.JSpinner spinner = new javax.swing.JSpinner()
spinner.setModel(new javax.swing.SpinnerDateModel());
    spinner.addChangeListener(new javax.swing.event.ChangeListener() {
        @Override
        public void stateChanged(javax.swing.event.ChangeEvent evt) {
            System.out.println("Just a test");
        }
    });

The code above shows the message twice when u click only one time.


Solution

  • 2 events are generated: one for the value being deselected and another for the new value being selected in the component. As @camickr notes in his comment this behavior occurs in SpinnerDateModel but not in the default SpinnerNumberModel

    As a workaround you could use

    spinner.addChangeListener(new ChangeListener() {
    
        Object lastValue;
    
        @Override
        public void stateChanged(ChangeEvent evt) {
    
            if (lastValue != null && !spinner.getValue().equals(lastValue)) {
               // expensive code calls here!
            }
            lastValue = spinner.getValue();
        }
    });
    

    This wont prevent the listener being called twice but will prevent any expensive code being invoked unnecessarily