我不敢相信我还没有找到任何关于此的信息。它必须是一个非常常见的用例。
我想设置我的 TextField (JavaFX),以便用户只能按模式输入数据。例如,具有类似 (###) ###-#### 模式的标准美国电话号码。事后格式化没有问题,并且我看到很多关于将输入限制为数字以及正确位置的“(”、“)”和“-”的教程/示例,但我不希望用户必须输入括号和破折号 - 它们应该就在那里,并且数字应该在它们“周围”输入。
我一直在网页上看到这一点 - 所以 javascript 必须很容易做到这一点。我曾经使用一种非常简单的语言,例如:
myTextField.setInputPattern("(999) 999-9999") // yes this is fictional code
您可以对任何模式执行相同的操作 - ss#、日期输入、IP 地址等。令我有点惊讶的是,我在 JavaFX 中找不到相关的内容。
最佳答案
据我所知,目前还没有实现这样的功能。不过,您可以使用带有过滤器的 TextFormatter
来修改任何输入以遵循您的模式。
以下代码将 #
视为数字占位符,其余部分保持原样:
private static String clearText(String input) {
return input.replaceAll("\\D+", "");
}
private static UnaryOperator<Change> createPatternFilter(String pattern) {
Pattern digitsPattern = Pattern.compile("\\d*");
final int maxDigits = pattern.replaceAll("[^#]*", "").length();
return change -> {
String text = change.getText();
if (!digitsPattern.matcher(text).matches()) {
return null; // prevent inputs other than digits
}
if (change.getControlText().equals(change.getControlNewText())) {
return change; // allow all changes not modifying the text
}
String clearText = clearText(change.getControlNewText());
String clearPrefix = clearText(change.getControlNewText().substring(0, change.getAnchor()));
final int prefixLength = clearPrefix.length();
if (clearText.length() > maxDigits) {
if (prefixLength > maxDigits) {
return null; // cursor already positioned after the last digit placeholder
}
clearText = clearText.substring(0, maxDigits); // cut of excessive digits
}
StringBuilder resultText = new StringBuilder(pattern.length());
int index = 0;
int prefixIndex = 0;
// copy parts digits before the cursor
while (prefixIndex < prefixLength) {
char c = pattern.charAt(index);
if (c == '#') {
resultText.append(clearPrefix.charAt(prefixIndex));
prefixIndex++;
} else {
resultText.append(c);
}
index++;
}
// deal with following non-digit placeholders
char c;
while (index < pattern.length() && (c = pattern.charAt(index)) != '#') {
resultText.append(c);
index++;
}
int newAnchor = resultText.length();
String clearSuffix = clearText.substring(prefixLength);
int suffixIndex = 0;
// copy remaining digits
while (index < pattern.length() && suffixIndex < clearSuffix.length()) {
c = pattern.charAt(index);
if (c == '#') {
resultText.append(clearSuffix.charAt(suffixIndex));
suffixIndex++;
} else {
resultText.append(c);
}
index++;
}
resultText.append(pattern.substring(index));
change.setRange(0, change.getControlText().length());
change.setText(resultText.toString());
change.selectRange(newAnchor, newAnchor);
return change;
};
}
@Override
public void start(Stage primaryStage) {
String pattern = "(###) ###-####";
TextField tf = new TextField(pattern);
TextFormatter<String> formatter = new TextFormatter<>(createPatternFilter(pattern));
tf.setTextFormatter(formatter);
VBox content = new VBox(tf);
Scene scene = new Scene(content);
primaryStage.setScene(scene);
primaryStage.show();
}
关于JavaFX 在文本字段上按模式设置输入过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56247504/