如何获取与用户从 JFormattedTextField 看到的值相同的值?

发布于 2024-08-20 12:51:44 字数 1285 浏览 5 评论 0原文

我正在使用 NumberFormatterJFormattedTextField,但 .getValue() 不会返回与用户看到的值相同的值。

我认为输入字符串是使用 NumberFormats 解析方法进行解析的,并且我使用实际的区域设置从 NumberFormat.getNumberInstance(); 获取 Numberformat。所以我不认为我可以轻松地扩展它并编写我自己的解析方法?

在示例中,如果用户输入1234.487 getValue() 将返回: 1234.487 但用户将显示 1,234.49

另一个示例,使用 NumberFormat.getCurrencyInstance();。用户输入 1234.487getValue() 将返回 1234.487,但用户将显示 $1,234.49

相反,如果格式化程序无法在不进行舍入的情况下格式化值,我希望生成 ParseException。同样的情况,如果用户输入 4.35b6,默认情况下格式化程序将显示 4.35 并且该值将为 4.35,但我想要一个 ParseException,因为用户输入了无效值。

这是我尝试过的代码:

NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
final JFormattedTextField ftf = new JFormattedTextField(nf);
ftf.setValue(new BigDecimal("1234.50"));

// Print the value from ftf
final JTextField txt = new JTextField(12);
txt.addFocusListener(new FocusAdapter() {
    public void focusGained(FocusEvent e) {
        txt.setText(ftf.getValue().toString());
    }
});

如何获得与用户看到的相同的值?

I'm using a NumberFormatter and JFormattedTextField, but the .getValue() doesn't return the same value as the user is seeing.

I think the input-string is parsed using NumberFormats parse-method, and I get the Numberformat from NumberFormat.getNumberInstance(); with the actual Locale. So I don't think I easily can extend it and write my own parse-method?

In example, if the user types 1234.487
the getValue() will return:
1234.487 but the user will be displayed 1,234.49

Another example, using NumberFormat.getCurrencyInstance();. The user types 1234.487 and the getValue() will return 1234.487 but the user will be displayed $1,234.49

Instead, I want an ParseException be generated if the Formatter can't format the value without rounding. Same thing if the user types 4.35b6, by default the formatter will display 4.35 and the value will be 4.35, but I want a ParseException, because the user typed in an invalid value.

Here is the code that I have tried with:

NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
final JFormattedTextField ftf = new JFormattedTextField(nf);
ftf.setValue(new BigDecimal("1234.50"));

// Print the value from ftf
final JTextField txt = new JTextField(12);
txt.addFocusListener(new FocusAdapter() {
    public void focusGained(FocusEvent e) {
        txt.setText(ftf.getValue().toString());
    }
});

How to get the same value as the user is seeing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

痴意少年 2024-08-27 12:51:44

您应该扩展 NumberFormatter 而不是 NumberFormat 并重写 stringToValue ,以便它验证在解析字符串时是否返回原始值:

class StrictNumberFormatter extends javax.swing.text.NumberFormatter {
    @Override
    public Object stringToValue(String text) throws ParseException {
        Object parsedValue = super.stringToValue(text);
        String expectedText = super.valueToString(parsedValue);
        if (! super.stringToValue(expectedText).equals(parsedValue)) {
            throw new ParseException("Rounding occurred", 0);
        }
        return parsedValue;
    }

    public StrictNumberFormatter(NumberFormat nf) {
        super(nf);
    }
}

NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
JFormattedTextField.AbstractFormatter formatter = new StrictNumberFormatter(nf);
final JFormattedTextField ftf = new JFormattedTextField(formatter);
ftf.setValue(new BigDecimal("1234.50"));

此格式化程序如果舍入前后的值不匹配,将拒绝新文本。

注意:这比较,而不是字符串。它将容忍诸如删除分组字符 ("$1,000" => "$1000") 和尾随零 ("$1.20" =>) 等更改。 “$1.2”)。基本上,如果 NumberFormat 返回相同的值,那么它是可以接受的。但 NumberFormat 施加的任何限制仍然适用,例如您不得删除货币符号或插入前导空格等。

You should extend NumberFormatter rather than NumberFormat and override stringToValue so that it verifies that when the string is parsed you get back the original value:

class StrictNumberFormatter extends javax.swing.text.NumberFormatter {
    @Override
    public Object stringToValue(String text) throws ParseException {
        Object parsedValue = super.stringToValue(text);
        String expectedText = super.valueToString(parsedValue);
        if (! super.stringToValue(expectedText).equals(parsedValue)) {
            throw new ParseException("Rounding occurred", 0);
        }
        return parsedValue;
    }

    public StrictNumberFormatter(NumberFormat nf) {
        super(nf);
    }
}

NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
nf.setMinimumFractionDigits(2);
JFormattedTextField.AbstractFormatter formatter = new StrictNumberFormatter(nf);
final JFormattedTextField ftf = new JFormattedTextField(formatter);
ftf.setValue(new BigDecimal("1234.50"));

This formatter will reject the new text if the values before and after rounding do not match.

Note: this compares the values, not the strings. It will tolerate changes like removing grouping characters ("$1,000" => "$1000") and trailing zeros ("$1.20" => "$1.2"). Basically if the NumberFormat returns the same value then it is acceptable. But any restrictions imposed by the NumberFormat still apply, e.g. you must not remove the currency symbol or insert leading spaces etc.

以为你会在 2024-08-27 12:51:44

试试这个:

txt.setText(ftf.getFormatter().valueToString(ftf.getValue()));

您还必须处理 valueToString 方法抛出的 java.text.ParseException

编辑:
格式化程序可以设置为完全禁止无效条目,这可能会有所帮助:

    ((DefaultFormatter)ftf.getFormatter()).setAllowsInvalid( false );

Try this:

txt.setText(ftf.getFormatter().valueToString(ftf.getValue()));

You'll also have to handle the java.text.ParseException that the valueToString method throws.

Edit:
The formatter can be set to disallow invalid entries altogether, which might help:

    ((DefaultFormatter)ftf.getFormatter()).setAllowsInvalid( false );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文