具有严格解析数字格式

时间:2015-11-19 15:35:22

标签: java swing number-formatting jformattedtextfield

由于有人将我的其他问题(NumberFormat parse not strict enough)标记为重复并且没有删除重复的标签,尽管我指出它不同,我会再次将问题与我的解决方案一起发布。也许这对某人有帮助。我们走了:

我有一个带有Locale.US的NumberFormat的JFormattedTextField。因此小数点分隔符是点,分组分隔符是逗号。

现在我在此文本字段中键入字符串“1,23”并将焦点移动到另一个组件。我希望字符串消失(就像我输入“a”而不是“1,23”时那样),因为在使用Locale.US时它显然不是数字的有效表示。但相反,文本字段中的文本更改为“123”。

这是因为在解析时使用的NumberFormat并不严格,只是忽略逗号。

问题:在这种情况下,如何告诉NumberFormat抛出ParseException,以便在将焦点移动到另一个组件后文本字段为空?

测试代码:

    JDialog dialog = new JDialog();
    JPanel panel = new JPanel(new BorderLayout());
    dialog.getContentPane().add(panel);

    NumberFormat nf = NumberFormat.getInstance(Locale.US);
    JFormattedTextField textField = new JFormattedTextField(nf);
    textField.setText("1,23");
    panel.add(textField, BorderLayout.CENTER);
    panel.add(new JButton("focus"), BorderLayout.EAST);

    dialog.pack();
    dialog.setVisible(true);

将焦点从文本字段移动到按钮,文本将更改为“123”。

1 个答案:

答案 0 :(得分:1)

这是我的解决方案:

首先,我使用严格的解析创建自定义DecimalFormat。只允许数字和最多一个小数点。

    public class StrictDecimalFormat extends DecimalFormat {

        private static final Pattern NUMBER_PATTERN = Pattern.compile("^\\d*[.]?\\d*$");

        public Number parse(String text, ParsePosition pos) {
            Matcher matcher = NUMBER_PATTERN.matcher(text);
            if (matcher.matches()) {
                return super.parse(text, pos);
            }
            return null;
        }
    }

现在我将这个十进制格式用于我的JFormattedTextField。由于区域设置本身不能设置为十进制格式,我必须创建适当的DecimalFormatSymbols并进行设置。

    DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(Locale.US);
    DecimalFormat strictFormat = new StrictDecimalFormat();
    strictFormat.setDecimalFormatSymbols(decimalFormatSymbols);

    JDialog dialog = new JDialog();
    JPanel panel = new JPanel(new BorderLayout());
    dialog.getContentPane().add(panel);

    JFormattedTextField textField = new JFormattedTextField(strictFormat);
    textField.setText("1,23");
    panel.add(textField, BorderLayout.CENTER);
    panel.add(new JButton("focus"), BorderLayout.EAST);

    dialog.pack();
    dialog.setVisible(true);