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