5

I'm trying to setup a JSpinner using a SpinnerNumberModel with value = 0.0005, min = 0.0, max = 1.0, and step size = 0.0005. However, when I create a spinner with these parameters I observe very strange behavior. Rather than starting at 0.0005 and increasing by 0.0005 with each click of the up arrow, the value seems to stick at 0.

To make sure this isn't just a formatting issue, I printed out the value of the spinner after each change event. Surely enough, for each click of the up arrow, the console shows the value as 0 and then 0.0005, regardless how many times the spinner has been clicked.

Below is the code I've used to test this, including a spinner with slightly different values that works just fine for comparison purposes.

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setSize(200, 80);
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        final JSpinner spinner1 = new JSpinner(new SpinnerNumberModel(0.0005, 0.0, 1.0, 0.0005));
        final JSpinner spinner2 = new JSpinner(new SpinnerNumberModel(0.05, 0.0, 1.0, 0.05));
        panel.add(spinner1, BorderLayout.NORTH);
        panel.add(spinner2, BorderLayout.SOUTH);
        frame.add(panel);
        spinner1.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                System.out.println("spinner1: " + ((Number) spinner1.getValue()).doubleValue());
            }
        });
        spinner2.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                System.out.println("spinner2: " + ((Number) spinner2.getValue()).doubleValue());
            }
        });
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

}

Can anyone explain to me why spinner2 works as intended, but spinner1 does not?

Thanks.

Edit: Thanks to Peter for pointing out that the formatting of the spinner's text field actually has an effect on the stored value. To get the first spinner to work as intended, I added the line: spinner1.setEditor(new JSpinner.NumberEditor(spinner1, "0.0000"));.

David Thielke
  • 197
  • 1
  • 8
  • Thanks for the input. The actual project where I first encountered the issue is much more complex than this. The code I posted here is a very bare bones example demonstrating the issue. – David Thielke Dec 26 '11 at 09:13
  • Alright, I've edited the example to include a JPanel to hold the two spinners. Unfortunately, I still get the same wonky results for the first spinner. – David Thielke Dec 26 '11 at 09:23
  • I've use a JPanel and problem still remains. I've tried using (0.001, 0.0001) as JSpinner model's (value, step) and (0.0001, 0.001) as well. Neither works. But (0.001, 0.001) works instead. Does this implies a problem of accuracy presenting of JSpinner? – xorange Dec 26 '11 at 09:26

1 Answers1

9

the problem is this in the JFormattedTextField used by the spinner. In that editor you can find:

public void commitEdit() throws ParseException {
    AbstractFormatter format = getFormatter();

    if (format != null) {
        setValue(format.stringToValue(getText()), false, true);
    }
}

your spinner display 0.0005 as 0.0, if you increment it first put 0.0 in your model and then increments to 0.0005, you event actually captures it but your textfield only sees 0.0

so solution will be to change the formatting of the spinner textfield.

you can overide the editor

final JSpinner spinner1 = new JSpinner(new SpinnerNumberModel(0.0005, 0.0, 1.0, 0.0005)) {
      @Override
      protected JComponent createEditor( SpinnerModel model )
      {
        return new NumberEditor(this, "0.0000");//needed decimal format
      }
    };
Peter
  • 5,728
  • 20
  • 23