如果 TextField 具有无效输入,如何使用 JavaFX 绑定禁用按钮

How to use a JavaFX binding to disable a button if TextField has invalid input

我从 The Definitive Guide to Modern Java Clients with JavaFX 得到以下代码:

updateButton.disableProperty()
    .bind(listView.getSelectionModel().selectedItemProperty().isNull()
            .or(wordTextField.textProperty().isEmpty())
            .or(definitionTextArea.textProperty().isEmpty()));

我想修改它,如果输入 frequencyTextField 的字符串不是非负整数,按钮将被禁用。我在连词中添加了一个术语,如下所示:

updateButton.disableProperty()
    .bind(listView.getSelectionModel().selectedItemProperty().isNull()
            .or(isLegalFrequency(frequencyTextField.textProperty()).not())
            .or(wordTextField.textProperty().isEmpty())
            .or(definitionTextArea.textProperty().isEmpty()));

虽然可能不相关,但这里是测试有效性的方法:

    private BooleanProperty isLegalFrequency(StringProperty sp) {
        System.out.println("isLegalFrequency(" + sp.get() + ")");
        try {
            int value = Integer.parseInt(sp.get());
            return new SimpleBooleanProperty(value >= 0);
        } catch (NumberFormatException e) {
            return new SimpleBooleanProperty(false);
        }
    }

我的问题是该按钮始终处于禁用状态。我已经确定 isLegalFrequency() 在创建场景时只被调用一次。这是有道理的,因为我正在传递 frequencyTextField.textProperty(),而不是在其上调用方法(这可能会在幕后设置一个侦听器)。

有没有办法修改程序 而无需添加显式侦听器 使其表现如我所愿,或者是否有必要创建一个 ChangeListener frequencyTextField.textProperty?

一般来说,您可以创建任意方法:

private Boolean validate() {
    // arbitrary implementation here...
    // in your case something like
    if (listView.getSelectionModel().getSelectedItem() == null) return false ;
    if (wordTextField.getText().isEmpty()) return false ;
    if (definitionTextArea.getText().isEmpty()) return false ;
    if (! isLegalFrequency(frequencyTextField.getText())) return false ;
    return true ;
}

然后

updateButton.disableProperty().bind(Bindings.createBooleanBinding(
    () -> ! validate(),
    listView.getSelectionModel().selectedItemProperty(),
    frequencyTextField.textProperty(),
    wordTextField.textProperty(),
    definitionTextArea.textProperty()));

createBooleanBinding() 方法的参数是 Callable<Boolean>(即不接受参数并返回 Boolean 的方法)后跟 javafx.beans.Observable 的零个或多个实例(任何 属性 或 ObservableList 等都可以)。您应该在此处包含任何 属性(或其他可观察的),当它发生变化时应该触发重新计算 disableProperty()