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

How in Java I can create a field that can accept only digits and once dot?

我在网上找遍了,但我尝试过的所有方法都没有用....

我发现我可以使用一些 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);
        }
    });

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

我做错了什么?

这可能是最简单的有效代码:

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

如果有一个点,它后面必须跟一些数字。如果你想允许一个点然后 no 数字也一样,将 + 更改为 *:

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

请注意,对于 String#matches(),leading/trailing ^/$ 不是必需的,因为它们是 隐含的 ,因为整个 字符串必须匹配 matches() 到 return true.

不允许前导数字也变得更棘手,因为正则表达式 (\d+)?(\.\d*) 匹配空白字符串,所以你需要一个交替:

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

或负面展望:

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

小look头断言start后的下一个位置不是end(即input不为空)

我有一个 similar problem a while back. The problem wasn't with the regex, but my misunderstanding of how the filter works. My assumption, like yours was that the String text passed to the replace method, is the entire string, when it's really only the character being typed. Similar discussion here

虽然所有 regex kung-fu 可能是您在匹配 regex 方面寻找的东西(我不知道,这不是我的强项),但问题(假设)可以通过获取整个文档文本来修复,然后尝试匹配 that,即

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

"And I also need it to not to start with a dot and not to end with a dot"

从逻辑上考虑一下。为每个字符输入调用过滤器。但是您不想以 . 结尾,而是希望在中间的某个位置允许 .。不允许在末尾 . 完全否定 . 的可能性,因为您需要在下一个数字

之前的末尾键入 .

如果用户离开悬挂 .

,当字段失去焦点时,您可能只编写一个焦点侦听器来添加 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();
            }
        });
    }
}