如何在Java中我可以创建一个只能接受数字和一次点的字段?

时间:2015-05-11 12:22:17

标签: java regex swing jtextfield documentfilter

我看着网上所有我试过的东西都不起作用......

我发现我可以使用一些JTextFormatterField,但它不起作用。

然后我发现我可以使用DocumentFilter和正则表达式以及我所做的:

JTextField jFormattedTextFieldMoneyToConvert = new JTextField();
    ((AbstractDocument) jFormattedTextFieldMoneyToConvert.getDocument()).setDocumentFilter(new DocumentFilter(){
        Pattern regEx = Pattern.compile("^\\d+\\.?\\d*$");

        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
            Matcher matcher = regEx.matcher(text);
            if (!matcher.matches()) {
                return;
            }
            super.replace(fb, offset, length, text, attrs);
        }
    });

但它不起作用......它只接受数字。我希望它也接受点。我还需要它不要以点开头而不是用点结束。

我做错了什么?

2 个答案:

答案 0 :(得分:3)

这可能是最简单的代码:

if (text.matches("\\d+(\\.\\d+)?"))

如果有点,则必须后跟一些数字。如果您想要一个点,那么没有数字,请将+更改为*

if (text.matches("\\d+(\\.\\d*)?"))

请注意,对于String#matches(),前导/尾随^ / $不是必需的,因为暗示,因为整个 string matches()才能返回true

允许没有前导数字也变得更加棘手,因为正则表达式(\d+)?(\.\d*)匹配空白字符串,因此您需要更改:

if (text.matches("\\d+(\\.\\d*)?|\\.\\d+"))

或负面展望:

if (text.matches("(?!$)\\d*(\\.\\d*)?"))

小看头断言开始后的下一个位置不是结束(即输入不是空白)。

答案 1 :(得分:2)

我有similar problem a while back。问题不在于正则表达式,而是我对过滤器如何工作的误解。我和你的假设一样,传递给String text方法的replace是整个字符串,当它真的只是被输入的字符时。类似的讨论here

虽然所有@Bohemian's正则表达式功夫可能都是你所寻找的匹配正则表达式(我不知道,这不是我的强项),但问题(假设)可以修复通过获取整个文档文本,然后尝试匹配 ,即

String completeText = fb.getDocument().getText(0, fb.getDocument().getLength());
  

“我还需要它不要以点开头而不是以点结尾”

在逻辑上考虑一下这一秒。为每个字符输入调用过滤器。但是你不希望以.结束,但是你想在中间的某个地方允许.。最后不允许.否定.的可能性,因为您需要在下一个数字之前键入.

如果用户离开.

,您可能只需编写一个焦点监听器来添加0或删除.字段失去焦点

更新:完整示例

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

public class FilterDemo {

    public FilterDemo() {
        JFrame frame = new JFrame();
        frame.setLayout(new GridBagLayout());
        frame.setSize(300, 300);
        frame.add(createFilteredField());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

    }

    private JTextField createFilteredField() {
        JTextField field = new JTextField(20);
        AbstractDocument document = (AbstractDocument) field.getDocument();
        final int maxCharacters = 10;
        document.setDocumentFilter(new DocumentFilter() {
            @Override
            public void replace(FilterBypass fb, int offs, int length,
                    String str, AttributeSet a) throws BadLocationException {

                String text = fb.getDocument().getText(0,
                        fb.getDocument().getLength());
                text += str;
                if (text.matches("^\\d+\\.?\\d*$")) {   //  "^[0-9]+[.]?[0-9]{0,}$"
                    super.replace(fb, offs, length, str, a);
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }

            }

            @Override
            public void insertString(FilterBypass fb, int offs, String str,
                    AttributeSet a) throws BadLocationException {

                String text = fb.getDocument().getText(0,
                        fb.getDocument().getLength());
                text += str;
                if (text.matches("^\\d+\\.?\\d*$")) {
                    super.insertString(fb, offs, str, a);
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }
            }
        });
        return field;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new FilterDemo();
            }
        });
    }
}