JavaFX - 带有邮政编码正则表达式的文本字段

JavaFX - TextField with regex for zipcode

对于我的程序,我想使用一个 TextField,用户可以在其中输入邮政编码(德语)。为此,我尝试了您在下面看到的内容。如果用户输入的数字超过 5 位,则应立即删除每个额外的数字。当然字母是不允许的。

当我在 https://regex101.com/ 上使用此模式 ^[0-9]{0,5}$ 时,它会按照我的意图进行操作,但是当我在 JavaFX 中尝试此操作时,它不起作用。但是我还没有找到解决方案。

谁能告诉我我做错了什么?

编辑:对于尚未使用 JavaFX 的人:当用户仅输入一个字符时,将调用方法 check(String text)。所以结果也应该为真,当有 1 到 5 位数字时。但不会更多 ;-)


public class NumberTextField extends TextField{

    ErrorLabel label;

    NumberTextField(String text, ErrorLabel label){
        setText(text);
        setFont(Font.font("Calibri", 17));
        setMinHeight(35);
        setMinWidth(200);
        setMaxWidth(200);
        this.label = label;
    }

    NumberTextField(){}

    @Override
    public void replaceText(int start, int end, String text){
        if(check(text)) {
            super.replaceText(start, end, text);
        }
    }

    @Override
    public void replaceSelection(String text){
        if(check(text)){
            super.replaceSelection(text);
        }
    }

    private boolean check(String text){
        if(text.matches("^[0-9]{0,5}$")){
            label.setText("Success");
            label.setBlack();
            return true;
        } else{
            return false;
        }
    }

您的原始表达式应该可以正常工作,但如果我们希望验证 five-digits zip,我们可能希望删除 0 量词:

^[0-9]{5}$
^\d{5}$

出于验证目的,我们可能希望保留开始和结束锚点,但是为了测试,我们可以删除并查看:

[0-9]{5}
\d{5}

其他一些字符可能会通过我们的输入,这是我们不希望的。

Demo

测试

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "^[0-9]{5}$";
final String string = "01234\n"
     + "012345\n"
     + "0\n"
     + "1234";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

while (matcher.find()) {
    System.out.println("Full match: " + matcher.group(0));
    for (int i = 1; i <= matcher.groupCount(); i++) {
        System.out.println("Group " + i + ": " + matcher.group(i));
    }
}

您无需扩展 TextField 即可执行此操作。事实上,我建议使用 TextFormatter,因为这样更容易实现:
它不需要您覆盖多个方法。您只需要根据有关所需输入的数据来决定是否允许更改。

final Pattern pattern = Pattern.compile("\d{0,5}");
TextFormatter<?> formatter = new TextFormatter<>(change -> {
    if (pattern.matcher(change.getControlNewText()).matches()) {
        // todo: remove error message/markup
        return change; // allow this change to happen
    } else {
        // todo: add error message/markup
        return null; // prevent change
    }
});
TextField textField = new TextField();
textField.setTextFormatter(formatter);