Recommended way to restrict input in JavaFX textfield

…衆ロ難τιáo~ 提交于 2019-12-09 10:27:23

问题


It may seem the question is the duplicate of this. But my question is i have developed a integer textfield in JavaFX by two ways. The code is given below

public class FXNDigitsField extends TextField
{
private long m_digit;
public FXNDigitsField()
{
    super();
}
public FXNDigitsField(long number)
{
    super();
    this.m_digit = number;
    onInitialization();
}

private void onInitialization()
{
    setText(Long.toString(this.m_digit));
}

@Override
public void replaceText(int startIndex, int endIndex, String text)
{
    if (text.matches(Constants.DIGITS_PATTERN) || text.equals(Constants.EMPTY_STRING)) {
        super.replaceText(startIndex, endIndex, text);
    }
}

@Override
public void replaceSelection(String text)
{
    if (text.matches(Constants.DIGITS_PATTERN) || text.equals(Constants.EMPTY_STRING)) {
        super.replaceSelection(text);
    }
}
}

And the second way is by adding an event Filter.

The code snippet is given.

 // restrict key input to numerals.
this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
  @Override public void handle(KeyEvent keyEvent) {
    if (!"0123456789".contains(keyEvent.getCharacter())) {
      keyEvent.consume();
    }
  }
});

My question is which is the slandered way to do this? Can anyone help me to pick up the right?


回答1:


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



回答2:


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)




回答3:


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



回答4:


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.



来源:https://stackoverflow.com/questions/15615890/recommended-way-to-restrict-input-in-javafx-textfield

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