These are tricky.
The first note is that you are using change.getText(), which gives the text being added or removed; you want to test the resulting text (i.e. the text after adding or deleting). For this, use change.getControlNewText().
For example, if the current text in the text field is "255.2", and the user types a "5", then change.getText() will return "5", whereas change.getControlNewText() will return "255.25".
This still leaves the main issue, which is that the filter is being applied to every individual change to the text, and you are testing for a complete ip address. So, for example, to type "255.255.255.255", the user would first type "2". You test (even with change.getControlNewText()) if "2" matches your regular expression, it fails (because it's not a complete IP address), and so the change is vetoed. On the next key typed, change.getControlNewText() will be "25", and so on. So you want the entire sequence "2", "25", "255", "255.", "255.2", etc, etc to pass your filter. You also need the filter to accept the user deleting characters, copying and pasting, and so on.
So you really need a regex that tests for partial entries, instead of complete entries, which is of course a little trickier to get right. The following is an example, not intended to be bullet-proof, but should get you on the right track (at least). Note that you probably want additional validation when the user commits the value, to check you have a complete, valid ip address.
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);
}
}