JavaFX TextField - Allow only one letter to be typed

后端 未结 1 507
被撕碎了的回忆
被撕碎了的回忆 2021-01-06 06:35

I\'m trying to make a Sudoku game in JavaFX but I can\'t figure out how to only allow one letter to be entered. Would the answer to this to be to call the textfield and do:

相关标签:
1条回答
  • 2021-01-06 07:20

    You can use a TextFormatter to do this. The TextFormatter can modify the changes that are made to the text in the text field if it has a filter associated with it. The filter is a function that takes a TextFormatter.Change object and returns an object of the same type. It can return null to veto the change entirely, or modify it.

    So you can do

    TextField textField = new TextField();
    textField.setTextFormatter(new TextFormatter<String>((Change change) -> {
        String newText = change.getControlNewText();
        if (newText.length() > 1) {
            return null ;
        } else {
            return change ;
        }
    });
    

    Note though that the TextFormatter can also be used to convert the text to a value of any type you like. In your case, it would make sense to convert the text to an Integer, and also to only allow integer input. As a final addition to the user experience, you can modify the change so that if the user types a digit, it replaces the current content (instead of ignoring it if there are too many characters). The whole thing would look like this:

        TextField textField = new TextField();
    
        // converter that converts text to Integers, and vice-versa:
        StringConverter<Integer> stringConverter = new StringConverter<Integer>() {
    
            @Override
            public String toString(Integer object) {
                if (object == null || object.intValue() == 0) {
                    return "";
                }
                return object.toString() ;
            }
    
            @Override
            public Integer fromString(String string) {
                if (string == null || string.isEmpty()) {
                    return 0 ;
                }
                return Integer.parseInt(string);
            }
    
        };
    
        // filter only allows digits, and ensures only one digit the text field:
        UnaryOperator<Change> textFilter = c -> {
    
            // if text is a single digit, replace current text with it:            
            if (c.getText().matches("[1-9]")) {
                c.setRange(0, textField.getText().length());
                return c ;
            } else 
            // if not adding any text (delete or selection change), accept as is    
            if (c.getText().isEmpty()) {
                return c ;
            }
            // otherwise veto change
            return null ;
        };
    
        TextFormatter<Integer> formatter = new TextFormatter<Integer>(stringConverter, 0, textFilter);
    
        formatter.valueProperty().addListener((obs, oldValue, newValue) -> {
            // whatever you need to do here when the actual value changes:
            int old = oldValue.intValue();
            int updated = newValue.intValue();
            System.out.println("Value changed from " + old + " to " + new);
        });
    
        textField.setTextFormatter(formatter);
    
    0 讨论(0)
提交回复
热议问题