严格解析数字格式的JFormattedTextField
JFormattedTextField with strict parsing number format
由于有人错误地将我的另一个问题(NumberFormat parse not strict enough)标记为重复并且没有删除重复的标签,尽管我指出它是不同的,我会post再次提出问题以及我的解决方案。也许对某人有帮助。我们开始了:
我有一个带有 NumberFormat 的 JFormattedTextField Locale.US。所以小数分隔符是点,分组分隔符是逗号。
现在我在此文本字段中键入字符串“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”。
这是我的解决方案:
首先,我创建了一个经过严格解析的自定义 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);
由于有人错误地将我的另一个问题(NumberFormat parse not strict enough)标记为重复并且没有删除重复的标签,尽管我指出它是不同的,我会post再次提出问题以及我的解决方案。也许对某人有帮助。我们开始了:
我有一个带有 NumberFormat 的 JFormattedTextField Locale.US。所以小数分隔符是点,分组分隔符是逗号。
现在我在此文本字段中键入字符串“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”。
这是我的解决方案:
首先,我创建了一个经过严格解析的自定义 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);