【问题标题】:DecimalFormat point and comma as decimalSeparatorDecimalFormat 点和逗号作为小数分隔符
【发布时间】:2017-09-30 23:32:42
【问题描述】:

我曾经写过这段代码来格式化JFormattedTextField的输入

DecimalFormat decimalFormat = new DecimalFormat("#0.00");
NumberFormatter nf = new NumberFormatter(decimalFormat);
nf.setValueClass(Double.class);
nf.setAllowsInvalid(true);
nf.setOverwriteMode(false);
tfPreisIntern = new JFormattedTextField(nf);

一段时间后,我意识到如果用户输入例如4,50 而不是4.50 则该值设置为4.00 而不是4.504,50 时会出现问题。我认为这是我的DecimalFormat 的问题。现在我的问题是,是否可以使用逗号和点作为十进制分隔符?变通方法也可以

我将值从JFormattedTextField 转换为BigDecimal 的方法:

public static BigDecimal getBigDecimal(Object value) {
    BigDecimal ret = null;
    if (value != null) {
        if (value instanceof BigDecimal) {
            ret = (BigDecimal) value;
        } else if (value instanceof String) {
            ret = new BigDecimal((String) value);
        } else if (value instanceof BigInteger) {
            ret = new BigDecimal((BigInteger) value);
        } else if (value instanceof Number) {
            ret = new BigDecimal(((Number) value).doubleValue());
        } else {
            throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass()
                    + " into a BigDecimal.");
        }
    }
    return ret;
}

我在这里看到的逗号问题是构造函数BigDecimal(string) 只允许小数点而不是逗号

编辑:

现在尝试像这样使用MaskFormatter

    MaskFormatter mask = new MaskFormatter("*#.##");
    mask.setPlaceholderCharacter(' ');
    mask.setCommitsOnValidEdit(false);

但我不能输入像2.50 这样的值。这只有在我使用像 #.## 这样的掩码时才有效。但我需要有可能在点之前有 1 位和 2 位数字的值

【问题讨论】:

  • 我猜setAllowsInvalid(true) 将允许解析和无效值,但会给你最接近的值,使用comma,只有左边部分会匹配,所以它无法检索@ 987654340@。我没有文档(还)来写一个关于这个的答案
  • 关于你的编辑,我不久前也遇到过类似的问题,幸运的是,格式只有"123456.789""123456,789",所以只有小数分隔符,所以我简单地替换@987654343 @ 和 . 匹配 BigDecimal 要求,但如果你有机会得到 "123,456.789",你就不能再使用它了。
  • @AxelH 这会起作用,但文本字段也应该始终显示发布的十进制格式。我也想过这个解决方案,但我无法让它工作,因为我必须将所有内容更改为正常的 JTextFields,然后许多方法无法按预期工作
  • 如回答 cmets 中所述,您可能需要关注此guide on formatted textfield。这可能会帮助你

标签: java number-formatting decimalformat


【解决方案1】:

当您查看 Oracle tutorial 时,您会发现:

  • 对于格式化,可以改变格式化符号,但是
  • 解析没有这样的东西。

这很有意义:您只是在问“我希望用户能够处理各种不一致的数据;代码会神奇地将其转化为用户的意思”。

改善用户体验的一种方法:而不是使用格式化的文本字段;您可以简单地允许用户输入 strings。然后你编写验证器,让“魔法”发生。

换句话说:如果您希望“4,59”和“4.59”得到相同的结果,那么您需要为此编写代码。这可能就像使用indexOf() 来计算“。”一样简单。或 "," 出现在传入字符串中 (ONCE);然后尝试对使用不同模式的每个案例使用“格式化”解析。如果您决定走那条通往深渊的陡峭路线,请开始阅读有关 InputVerifiers here 的信息。

当然:这可能会很复杂;因为如前所述;您基本上是在允许用户输入 whatever 数据;并期望他的意思。

我个人的两分钱:在该文本字段周围放置大量警告/示例;并允许完全一种基于语言环境的输入。当他违反这一点时,会打用户的手指。

【讨论】:

  • 这有点复杂,因为一些本地使用., 作为千位分隔符。 100,000.00。但这个想法当然是正确的。要添加更多信息,格式使用. 作为小数分隔符的占位符。所以会根据本地来匹配正确的分隔符
  • 我们可以简单地假设永远不会输入千位,即使不应该有千位分隔符。如果我使用这个解决方案,我认为我需要一些帮助来重写一个方法,该方法给我一个来自不同类的 BigDecimal,因为我认为验证必须在那里进行。用户的问题是有些是英语,有些是德语,因此有不同的小数分隔符
  • @AxelH 它是一个价格字段,因此分数应该只允许 2 位数,不能更多
  • @XtremeBaumer 在金融领域,您有 3 位数字的货币(只有少数),但您也可以有 3、6、8 位小数的价格。因此,不幸的是,这并非在所有地方都是正确的。但这适用于本地系统,例如商店管理或不处理燃料的任何事物(也是 3 位小数)
  • 我想我可以使用 maskformatter,但我似乎无法让最后一件事起作用,即格式为 ##.## 并且仍然显示像 2.50 这样的值。如果我使用#.## 格式,那么我无法显示12.30 之类的值。如果您能给我提示以完成这项工作,我将不胜感激
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
相关资源
最近更新 更多