3

我正在使用NumberFormatterJFormattedTextField,但.getValue()不会返回与用户所看到的值相同的值。如何获得与用户从JFormattedTextField中看到的相同的值?

我认为输入字符串是使用NumberFormats parse-method解析的,我从NumberFormat.getNumberInstance();获得Numberformat与实际的Locale。所以我不认为我可以轻松扩展它并编写我自己的分析方法?

在示例,如果用户键入1234.487getValue()将返回: 1234.487但用户将使用NumberFormat.getCurrencyInstance();显示1,234.49

又如。用户类型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()); 
    } 
}); 

如何获得相同的值,用户正在观看?

+1

此问题相关,并且将改进解决方案:http:// stackoverflow。com/questions/1680120/javas-decimalformat-h​​ow-to-reject-invalid-input-with-grouped-decimals – Jonas 2010-02-05 13:07:23

回答

6

您应该扩展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施加的任何限制仍然适用,例如,您不得删除货币符号或插入前导空格等。

+0

这对货币格式化程序是否适用? – Ash 2010-02-05 12:41:11

+0

@Ash,是的,我只是用'getCurrencyInstance()'试了一下。它应该与任何有效的'NumberFormat'一起工作。 – finnw 2010-02-05 12:57:34

+0

使用此解决方案编辑文本字段变得更加容易,所以我将采用此方法。谢谢! – Jonas 2010-02-06 13:53:31

3

试试这个:

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

你还必须处理java.text.ParseExceptionvalueToString方法抛出。

编辑: 格式化可以设置为完全禁止无效的项目,这可能有助于:

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

这是行不通的。然后您必须再次解析字符串,因为该字符串包含格式,如currencysymbol和数字分组。我不认为有一个字符串currencysymbols解析器? – Jonas 2010-02-05 10:37:26

+1

当我运行你的代码(通过上面的改变)并输入“1234.487”时,我在两个字段中都看到“1,234.49”。这不是你想要的吗? – Ash 2010-02-05 10:49:19

+0

不,我想要的值,而不是字符串,所以我可以做计算。如果我想这样,我可以使用getText()。我认为,如果用户键入三个小数位数,就应该生成一个ParseException,格式化程序不应该舍入,这很重要。如果我喜欢你的例子,这个值有1到2之间的分组符号,所以我必须再次解析它。 – Jonas 2010-02-05 11:07:18

相关问题