【问题标题】:JavaFX - TextField with regex for zipcodeJavaFX - 带有正则表达式的邮政编码文本字段
【发布时间】:2019-06-04 14:39:05
【问题描述】:

对于我的程序,我想使用一个 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;
        }
    }

【问题讨论】:

  • 您不需要^$,因为使用.matches()full 字符串必须已经与模式匹配。无论如何,它应该工作。 "12345".matches("^[0-9]{0,5}$") 给我true
  • 你如何告诉Java这个字段只有数字?你如何告诉 Java 字段长度只有 5 ?您可以每次都用这个正则表达式替换该字段 find ^\D*([0-9]{0,5})[\S\s]* replace $1
  • @mumpitz 你是对的,但是当我在文本字段中输入更多数字时,它不会删除额外的数字。只有字母会被立即删除

标签: regex javafx textfield zipcode


【解决方案1】:

您无需扩展 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);

【讨论】:

    【解决方案2】:

    您的原始表达式应该可以正常工作,但如果我们希望验证一个五位数的 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));
        }
    }
    

    【讨论】:

    • 问题是用户一开始只输入一个数字,然后输入第二个,以此类推。但他不能输入超过 5 位数字。在您的示例中很好,但是在 JavaFX 中,每次用户输入一个字符时,都会调用方法 check(String text) ,当然,当用户只输入一位数字时,它无法匹配此模式 [0-9]{5 }
    猜你喜欢
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多