2

I am looking for an alternative of Swing InputVerifier to JavaFX TextField.

The Swing InputVerifier will prevent input that does verify.

Consider the following Swing JTextField code:

InputVerifier iv = new InputVerifier() {
    /* (non-Javadoc)
     * @see javax.swing.InputVerifier#verify(javax.swing.JComponent)
     */
    @Override
    public boolean verify(JComponent input) {
        JTextField tf = (JTextField) input;
        if (!myRegExTool.matches(tf.getText())) {
            return false;
        }
        return true;
    }
};
jinstance.setInputVerifier(iv);

I could use TextField.setOnKeyTyped or a listener to TextField.textProperty to check the typed text. However that will not prevent invalid text to get into the TextField. I could however delete typed text that does not verify, but that is not a good solution.



Solution: As suggested by James_D a TextFormatter with a filter was the perfect solution

    UnaryOperator<Change> textFilter = change -> {
        String input = change.getText();
        if (!myRegExTool.matches(input)) {
            return null;
        }
        return change;
    };
    instance.setTextFormatter(new TextFormatter<String>(textFilter));
DJViking
  • 832
  • 1
  • 12
  • 29
  • Use a [`TextFormatter`](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TextFormatter.html) with a filter. – James_D Jul 10 '17 at 09:59
  • Thanks. That was the perferct solution here. To get the credit, you should create an answer I can acccept (I could edit it afterwards with my code example). – DJViking Jul 10 '17 at 10:19

2 Answers2

1

I have IntegerField control with StringConverter, UnaryOperator and TextFormatter. Maybe helpful for you!

import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.util.StringConverter;
import javafx.util.converter.IntegerStringConverter;
import java.util.function.UnaryOperator;

public class IntegerField extends TextField {

public IntegerField() {
    super();
    StringConverter<Integer> integerStringConverter = new IntegerStringConverter();
    UnaryOperator<TextFormatter.Change> filter = getFilter();
    setTextFormatter(new TextFormatter<>(integerStringConverter, null, filter));
    setOnAction(event -> integerStringConverter.fromString(this.getText()));
}

private UnaryOperator<TextFormatter.Change> getFilter() {
    return change -> {
        String text = change.getText();
        if (!change.isContentChange()) {
            return change;
        }
        if (text.matches("[0-9]*")) {
            return change;
        }
        return null;
    };
}

public Integer getValue() {
    return Integer.valueOf(this.getText());
}

}
Cem Ikta
  • 1,330
  • 12
  • 12
1

As first suggested by James_D a TextFormatter with filter was the solution.

TextField instance = new TextField();
UnaryOperator<Change> textFilter = change -> {
    String input = change.getText();
    if (!change.isContentChange()) {
        return change;
    }
    if (!myRegExTool.matches(input)) {
        return null;
    }
    return change;
};
instance.setTextFormatter(new TextFormatter<String>(textFilter));
DJViking
  • 832
  • 1
  • 12
  • 29