JavaFX:运行 ChangeListener

标签 javafx changelistener

我可以在初始化时运行 ChangeListener 内的更改方法吗? 因为它仅在发生更改时运行。例如,我有一个 TextField,当它为空时,我想将其值设置为 0,我这样做:

textField.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
            if (!newValue.matches("\\d*")) {
                textField.setText(newValue.replaceAll("[^\\d]", ""));
            }

            if (newValue.isEmpty())
                textField.setText("0");

        }
    });

但是在应用程序启动时,不会调用更改的方法。那么如何解决这个问题呢?

最佳答案

无法访问添加到属性的监听器。显然你可以只保留对它的引用:

ChangeListener<String> textFieldListener = (observable, oldValue, newValue) -> {

    if (!newValue.matches("\\d*")) {
        textField.setText(newValue.replaceAll("[^\\d]", ""));
    }

    if (newValue.isEmpty())
        textField.setText("0");

};

textField.textProperty().addListener(textFieldListener);
textFieldListener.changed(null, null, textField.getText());

或者,也许更自然的是,将实际功能转移到不同的方法:

textField.textProperty().addListener((observable, oldValue, newValue) -> vetoTextFieldChanges());
vetoTextFieldChanges();

// ...

private void vetoTextFieldChanges() {
    String newText = textField.getText();
    if (!newText.matches("\\d*")) {
        textField.setText(newText.replaceAll("[^\\d]", ""));
    }

    if (newText.isEmpty())
        textField.setText("0");
}

请注意,观察更改然后在更改与业务逻辑不一致时进行修改的整个方法并不是很令人满意。例如,如果您有其他监听器注册了该属性,他们可能会看到文本的中间(无效)值。支持的方法是使用 TextFormatterTextFormatter 都允许您在 textProperty() 更新之前否决对文本请求的更改,并将文本转换为一个合适的值。所以在你的情况下你可以这样做:

UnaryOperator<TextFormatter.Change> filter = change -> {

    // remove any non-digit characters from inserted text:
    if (! change.getText().matches("\\d*")) {
        change.setText(change.getText().replaceAll("[^\\d]", ""));
    }

    // if new text is empty, replace all text with "0":
    if (change.getControlNewText().isEmpty()) {
        change.setRange(0, change.getControlText().length());
        change.setText("0");
    }

    return change ;
};

TextFormatter<Integer> formatter = new TextFormatter<Integer>(new IntegerStringConverter(), 0, filter);
textField.setTextFormatter(formatter);

现在您可以使用格式化程序通过格式化程序的 value 属性直接获取(数字)值,并将它们绑定(bind)到您的模型等:

// assume model is a data model and valueProperty() returns a Property<Integer>:
formatter.valueProperty().bindBidirectional(model.valueProperty());

请注意,当模型更改时,这样的绑定(bind)将更新格式化程序(从而更新文本字段),并且还将根据您的模型值对其进行初始化(从而为您的原始问题提供解决方案)。

关于JavaFX:运行 ChangeListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41332483/

相关文章:

JavaFx:使 ChangeListener 无效

intellij-idea - 在 IntelliJ 中设置 JavaFX - VM 选项根本不起作用

Javafx仿射变换

JavaFX Web 引擎无法完全运行 javascript

java - JavaFX GUI 可以与 Netbeans IDE 完美配合,但不能与 eclipse 配合使用

java - 如何为循环中创建的 100 个文本字段创建一个changeListener?

带有 ChangeListener 的 JavaFX TableView 用于多选

java - 限制菜单中可见行数: JavaFX

Java Swing : JButtons and JSliders will not work individually