java - 如何在 JSpinner 中禁用值的舍入

标签 java swing numbers rounding jspinner

我有一个最大小数位数为 6 的 JSpinner。因此,当我输入 1.1234567 时,它会四舍五入为 1.123457

但我的要求是,当用户以自由文本形式输入值时,我想禁用舍入并将值设置为微调器(1.1234567)。但是,如果用户单击微调器箭头按钮,它可以被舍入。

最佳答案

该值通常由 JSpinner 的编辑器格式化。您更改编辑器格式化显示值的方式,这将使实际模型值保持不变

编辑器通常由 JFormattedTextField 支持,如果能够捕获它并配置它就好了...

可能有几种方法可以做到这一点,但我选择使用 NumberFormat,因为我知道如何控制小数位数和舍入模式

首先,我们需要实现一个JFormattedTextField.AbstractFormatter

public class NumberFormatFormatter extends DefaultFormatter {

    private NumberFormat format;

    public NumberFormatFormatter(NumberFormat format) {
        this.format = format;
    }

    @Override
    public Object stringToValue(String string) throws ParseException {
        System.out.println("stringToValue: " + string);
        return format.parse(string);
    }

    @Override
    public String valueToString(Object value) throws ParseException {           
        String text = format.format(value);
        System.out.println("valueToString: " + value + "; " + text);
        return text;
    }

}

然后将其包装在 AbstractFormatterFactory

NumberFormat numberInstance = NumberFormat.getNumberInstance();
numberInstance.setMaximumFractionDigits(6);
numberInstance.setMinimumFractionDigits(0);
numberInstance.setRoundingMode(RoundingMode.DOWN);

JFormattedTextField.AbstractFormatter format = new NumberFormatFormatter(numberInstance);
DefaultFormatterFactory dff = new DefaultFormatterFactory(format);

然后我们配置 JSpinner 并创建一个新的 NumberEditor 来满足我们的需要

JSpinner spinner = new JSpinner(new SpinnerNumberModel());
JSpinner.NumberEditor editor = new JSpinner.NumberEditor(spinner, "0.0#####");
JFormattedTextField textField = editor.getTextField();
textField.setFormatterFactory(dff);
textField.setColumns(10);
spinner.setEditor(editor);

不要忘记将编辑器应用于 JSpinner ;)。

这可能看起来很多(我当然这么认为),但是将它包装到您自己的编辑器类的实现中并不需要太多,该编辑器类只是将 NumberFormat 作为参数,因为一个想法。

这种方法将“显示”留给了编辑器,但不会影响模型中的基础值,因此,如果您输入 1.123456789,模型仍将返回 1.123456789,但它会显示 1.123456

查看 How to Use Formatted Text FieldsHow to Use Spinners 了解更多详情

Spinner

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.DefaultFormatter;
import javax.swing.text.DefaultFormatterFactory;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {

            NumberFormat numberInstance = NumberFormat.getNumberInstance();
            numberInstance.setMaximumFractionDigits(6);
            numberInstance.setMinimumFractionDigits(0);
            numberInstance.setRoundingMode(RoundingMode.DOWN);

            JFormattedTextField.AbstractFormatter format = new NumberFormatFormatter(numberInstance);
            DefaultFormatterFactory dff = new DefaultFormatterFactory(format);

            JSpinner spinner = new JSpinner(new SpinnerNumberModel());
            JSpinner.NumberEditor editor = new JSpinner.NumberEditor(spinner, "#0.######");
            JFormattedTextField textField = editor.getTextField();
            textField.setFormatterFactory(dff);
            textField.setColumns(10);
            spinner.setEditor(editor);

            setLayout(new GridBagLayout());

            spinner.setValue(1.1234567d);

            add(spinner);
        }

        public class NumberFormatFormatter extends DefaultFormatter {

            private NumberFormat format;

            public NumberFormatFormatter(NumberFormat format) {
                this.format = format;
            }

            @Override
            public Object stringToValue(String string) throws ParseException {
                System.out.println("stringToValue: " + string);
                return format.parse(string);
            }

            @Override
            public String valueToString(Object value) throws ParseException {
                String text = format.format(value);
                System.out.println("valueToString: " + value + "; " + text);
                return text;
            }

        }

    }

}

关于java - 如何在 JSpinner 中禁用值的舍入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31065702/

相关文章:

java - Swing 中的注音假名(或 GUI 替代品……)

Java Swing : cannot spread components in whole JPanel with GridBagLayout

android - 使用输入类型编号禁用编辑文本的自动建议

java - 数字解析库

java - BIP4435聚合回复节点收到回复消息,回复消息 ID 为 :

java - Android 多种实现

java - 即使数字相同也会导致 SpinnerNumberModel 更新

java - 从 SQLite 和 Cursor 比较问题中获取值(value)

java - 类型不匹配 : cannot convert from org. slf4j.Logger 到 org.apache.log4j.Logger

java - java中如何用科学计数法表示数字?