Нечетное поведение SpinnerNumberModel в Java - PullRequest
5 голосов
/ 26 декабря 2011

Я пытаюсь настроить JSpinner, используя SpinnerNumberModel со значением = 0,0005, минимум = 0,0, максимум = 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"));.

1 Ответ

9 голосов
/ 26 декабря 2011

проблема в том, что в 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
      }
    };
...