Это сложно.
Первое примечание заключается в том, что вы используете change.getText()
, что дает добавление или удаление текста; вы хотите проверить полученный текст (т. е. текст после добавления или удаления). Для этого используйте change.getControlNewText()
.
Например, если текущий текст в текстовом поле "255.2"
, и пользователь вводит "5"
, то change.getText()
вернется "5"
, тогда как change.getControlNewText()
вернется "255.25"
.
Это все еще оставляет основную проблему, которая заключается в том, что фильтр применяется к каждому отдельному изменению текста, и вы тестируете полный IP-адрес. Так, например, чтобы ввести «255.255.255.255», пользователь сначала наберет «2». Вы тестируете (даже с change.getControlNewText()
), если «2» соответствует вашему регулярному выражению, он терпит неудачу (потому что это не полный IP-адрес), и поэтому изменение накладывается вето. На следующем введенном ключе change.getControlNewText()
будет "25"
и так далее. Таким образом, вы хотите, чтобы вся последовательность "2
», "25"
, "255"
, "255."
, "255.2"
, и т.д., и т.д., чтобы передать свой фильтр. Кроме того, необходимо фильтр принять пользователю удаление символов, копирование и вставка, и так далее.
Так вам действительно нужно регулярное выражение, которое проверяет частичные записи, а не полные записи, что, конечно, немного сложнее, чтобы получить право. Ниже приведен пример, который не предназначен для пуленепробиваемых, но должен получить вас на правильном пути (по крайней мере). Обратите внимание, что вы, вероятно, хотите получить дополнительную валидацию, когда пользователь совершит это значение, чтобы проверить, что у вас есть полный действительный IP-адрес.
import java.util.function.UnaryOperator;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class IPTextFieldTest extends Application {
@Override
public void start(Stage primaryStage) {
TextField ipTextField = new TextField();
String regex = makePartialIPRegex();
final UnaryOperator<Change> ipAddressFilter = c -> {
String text = c.getControlNewText();
if (text.matches(regex)) {
return c ;
} else {
return null ;
}
};
ipTextField.setTextFormatter(new TextFormatter<>(ipAddressFilter));
StackPane root = new StackPane(ipTextField);
Scene scene = new Scene(root, 350, 120);
primaryStage.setScene(scene);
primaryStage.show();
}
private String makePartialIPRegex() {
String partialBlock = "(([01]?[0-9]{0,2})|(2[0-4][0-9])|(25[0-5]))" ;
String subsequentPartialBlock = "(\\."+partialBlock+")" ;
String ipAddress = partialBlock+"?"+subsequentPartialBlock+"{0,3}";
return "^"+ipAddress ;
}
public static void main(String[] args) {
launch(args);
}
}
Спасибо, все отлично! Но я не понимаю, почему он работает с вашим регулярным выражением, а не с моим, даже если я использую getControlNewText() вместо getText() . Мне просто нужно выяснить, как убедиться, что пользователь вводит что-то между двумя точками и, возможно, ноль впереди :) – Phoste
Потому что '' 2 "', '" 25 "', '" 255 "', '" 255. "', '" 255.2 "' и т. д. и т. д. не соответствуют вашему регулярному выражению. Он проверяет каждый раз, когда текст изменяется. –
Отредактированный ответ, чтобы уточнить последний пункт. Пожалуйста, примите ответ правильно, если он ответит на ваш вопрос. –