Recommended way to restrict input in JavaFX textfield

限于喜欢 提交于 2019-12-03 12:31:04
gmatagmis

The best way to add validation in TextField is a 3rd way. This method lets TextField finish all processing (copy/paste/undo safe). It does not require you to extend the TextField class. And it allows you to decide what to do with new text after every change (to push it to logic, or turn back to previous value, or even to modify it).

// fired by every text property changes
textField.textProperty().addListener(
  (observable, oldValue, newValue) -> {
    // Your validation rules, anything you like
    // (! note 1 !) make sure that empty string (newValue.equals("")) 
    //   or initial text is always valid
    //   to prevent inifinity cycle
    // do whatever you want with newValue

    // If newValue is not valid for your rules
    ((StringProperty)observable).setValue(oldValue);
    // (! note 2 !) do not bind textProperty (textProperty().bind(someProperty))
    //   to anything in your code.  TextProperty implementation
    //   of StringProperty in TextFieldControl
    //   will throw RuntimeException in this case on setValue(string) call.
    //   Or catch and handle this exception.

    // If you want to change something in text
    // When it is valid for you with some changes that can be automated.
    // For example change it to upper case
    ((StringProperty)observable).setValue(newValue.toUpperCase());
  }
);
Shreyas Dave

In both of your ways, you are not allowed to type characters other then numeric characters. But it will allow to paste any character there (Copy Text from any source and Paste in your TextField).

A good way to do validation is after submitting it,

Like (For integers):

try {
    Integer.parseInt(myNumField.getText());
} catch(Exception e) {
    System.out.println("Non-numeric character exist");
}

(or you can use any combination of yours + the above method)

JavaFX has a class TextFormatter for this use-case. It allows you to validate and adjust the text content before it is "commited" to the textProperty of the TextField.

See this example:

TextFormatter<String> textFormatter = new TextFormatter<>(change -> {
    if (!change.isContentChange()) {
        return change;
    }

    String text = change.getControlNewText();

    if (isValid(text)) { // your validation logic
        return null;
    }


    return change;
});

textField.setTextFormatter(textFormatter);

Similar of what Manuel Mauky posted, but in groovy is:

Note: This will prevent any other character except for digits to be input.

def digitsOnlyOperator = new UnaryOperator<TextFormatter.Change>() {
        @Override
        TextFormatter.Change apply(TextFormatter.Change change) {
            return !change.contentChange || change.controlNewText.isNumber() ? change : null
        }
}
textField.textFormatter = new TextFormatter<>(digitsOnlyOperator)

There is probably a shorter way to do it in groovy. If you know it, please post it here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!