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);
}
}