Странное поведение SpinnerNumberModel в Java

Я пытаюсь настроить JSpinner, используя SpinnerNumberModel со значением = 0,0005, min = 0,0, max = 1,0 и размером шага = 0,0005. Однако, когда я создаю счетчик с этими параметрами, я наблюдаю очень странное поведение. Вместо того, чтобы начинать с 0,0005 и увеличиваться на 0,0005 с каждым щелчком стрелки вверх, значение, кажется, остается равным 0.

Чтобы убедиться, что это не просто проблема форматирования, я распечатывал значение счетчика после каждого события изменения. Разумеется, для каждого щелчка стрелки вверх консоль показывает значение как 0, а затем 0,0005, независимо от того, сколько раз был нажат счетчик.

Ниже приведен код, который я использовал для проверки, включая счетчик с немного другими значениями, который отлично работает для целей сравнения.

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);
    }

}

Кто-нибудь может объяснить мне, почему spinner2 работает так, как задумано, а spinner1 нет?

Спасибо.

Редактировать: спасибо Питеру за указание на то, что форматирование текстового поля счетчика фактически влияет на сохраненное значение. Чтобы первый спиннер работал как надо, я добавил строку: spinner1.setEditor(new JSpinner.NumberEditor(spinner1, "0.0000"));.


person David Thielke    schedule 26.12.2011    source источник
comment
Спасибо за отзыв. Фактический проект, в котором я впервые столкнулся с проблемой, намного сложнее этого. Код, который я разместил здесь, представляет собой очень простой пример, демонстрирующий проблему.   -  person David Thielke    schedule 26.12.2011
comment
Хорошо, я отредактировал пример, добавив JPanel для хранения двух счетчиков. К сожалению, я все еще получаю те же шаткие результаты для первого счетчика.   -  person David Thielke    schedule 26.12.2011
comment
Я использую JPanel, и проблема все еще остается. Я пробовал использовать (0,001, 0,0001) в качестве модели JSpinner (значение, шаг) и (0,0001, 0,001). Ни то, ни другое не работает. Но вместо этого работает (0,001, 0,001). Означает ли это проблему точности представления JSpinner?   -  person xorange    schedule 26.12.2011


Ответы (1)


проблема в том, что JFormattedTextField используется счетчиком. В этом редакторе вы можете найти:

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

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

ваш счетчик отображает 0,0005 как 0,0, если вы увеличиваете его, сначала помещаете 0,0 в свою модель, а затем увеличиваете до 0,0005, ваше событие фактически захватывает его, но ваше текстовое поле видит только 0,0

поэтому решением будет изменить форматирование текстового поля счетчика.

вы можете перекрыть редактор

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
      }
    };
person Peter    schedule 26.12.2011
comment
Интересно... Я предположил, что счетчик сохраняет одно и то же значение двойной точности независимо от того, как оно форматируется текстовым полем. Спасибо! - person David Thielke; 26.12.2011
comment
Спасибо, Питер. Я отредактировал свой вопрос, включив в него дополнительную строку, которая служит той же цели. - person David Thielke; 26.12.2011