【问题标题】:JavaFX TextField - Allow only one letter to be typedJavaFX TextField - 只允许输入一个字母
【发布时间】:2016-03-28 05:40:47
【问题描述】:

我正在尝试在 JavaFX 中制作数独游戏,但我不知道如何只允许输入一个字母。对此的答案是调用文本字段并执行:

myTextField.setOnKeyPressed(e ->
{
    if (!myTextField.getText().length().isEmpty())
    {
        // Somehow reject the key press?
    }
}

上述方式不适用于复制粘贴...或大量其他内容等。使用这样的按键监听器似乎是一个非常糟糕的想法。一定有更好的东西吗?文本字段是否有一个属性,只允许输入某些字符,或者只允许输入一定数量的字符?

谢谢!

【问题讨论】:

  • 请注意,如果用户使用鼠标和上下文菜单进行复制和粘贴,则使用监听器进行按键操作将失败。链接问题中接受的答案也有缺陷;其他答案将起作用,但已过时,因为 JavaFX 8 有专门针对此用例的 API。

标签: java user-interface javafx textfield


【解决方案1】:

您可以使用TextFormatter 来执行此操作。 TextFormatter 可以修改对文本字段中的文本所做的更改,前提是它具有与之关联的过滤器。过滤器是一个函数,它接受一个TextFormatter.Change 对象并返回一个相同类型的对象。它可以返回null 以完全否决更改,或对其进行修改。

所以你可以这样做

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

请注意,TextFormatter 也可用于将文本转换为您喜欢的任何类型的值。在您的情况下,将文本转换为 Integer 并且只允许整数输入是有意义的。作为对用户体验的最后补充,您可以修改更改,以便如果用户键入数字,它会替换当前内容(而不是在字符过多时忽略它)。整个事情看起来像这样:

    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 " + updated);
    });
    
    textField.setTextFormatter(formatter);

【讨论】:

  • 哇,效果很好。我想有办法做到这一点,而不是听众。谢谢!
猜你喜欢
  • 2017-11-13
  • 1970-01-01
  • 1970-01-01
  • 2022-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 2022-12-04
相关资源
最近更新 更多