java - 在监听器中有效地使用监听器?

标签 java javafx

如果我在表单上下文中有多个 TextField,那么“提交”按钮如何保持禁用状态,直到任意数量 TextFields 不为空?

如果文本字段上只有一个 TextField 且带有 ChangeListener,则可以简单地完成此操作,但如何针对 x 实现它TextField 的?
其中x是一个> 1的数字。

一个文本字段示例
按钮的 .setDisable() 方法是通过 TextField 上的 ChangeListener 来实现的,检查该字段是否为空。

其行为:

  • 当文本字段为空时,按钮禁用
  • 当文本字段包含某些内容时,按钮启用

...正如预期的那样。

如果两个字段使用同一个监听器(如下所示),则它们的行为就像彼此独立一样。
例如。如果其中任何一个包含某些内容,则启用该按钮:

public void someMethod(){
    Dialog dialog = new Dialog();
    dialog.getDialogPane().getButtonTypes().addAll(ButtonType.APPLY, ButtonType.CANCEL);

    TextField textField1 = new TextField();
    textField1.setPromptText("field1");
    TextField textField2 = new TextField();
    textField2.setPromptText("field2");


    // add fields to gridpane
    GridPane gridPane = new GridPane();
    gridPane.add(textField1,0,0);
    gridPane.add(textField2,0,1);

    // add grid to dialog pane
    dialog.getDialogPane().setContent(gridPane);

    Node applyButton = dialog.getDialogPane().lookupButton(ButtonType.APPLY);
    applyButton.setDisable(true);

    ChangeListener<String> myChangeListener = new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
            applyButton.setDisable(newValue.trim().isEmpty());
        }
    };

    textField1.textProperty().addListener(myChangeListener);
    textField2.textProperty().addListener(myChangeListener);

    dialog.showAndWait();
}

如果使用相同的过程将独立的监听器添加到每个字段,情况也是如此:

textField1.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        applyButton.setDisable(newValue.trim().isEmpty());
    }
});


textField2.textProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
        applyButton.setDisable(newValue.trim().isEmpty());
    }
});
<小时/>

多次尝试
解决多个问题的一种方法是简单地将听众“分层”。这符合预期,在启用按钮之前,两个 TextField 都必须包含某些内容

    textField1.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
            // add listener to textField 2
            textField2.textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    applyButton.setDisable(newValue.trim().isEmpty());

                    // ... add listener to textField x
                }
            });
        }
    });

这个过程看起来效率很低!
如果我有 20 个 TextFields 怎么办?我应该“分层”20 层吗?

这是唯一的方法吗?如果不是,如何才能使流程更加高效?

最佳答案

您不需要在其他监听器中添加额外的监听器 - 您希望观察更改,无论先前的更改是否发生。

相反,您必须在每次更改时检查整个输入的有效性(所有文本字段均非空)。通过将所有 TextField 传递给一个方法,可以相当通用地完成此操作:

private void setButtonTextFieldListeners(Button button, TextField... textFields) {
    ChangeListener<String> listener = (observable, oldValue, newValue) -> {
        for (int i=0; i<textFields.length; i++) {
            if (textFields[i].getText()==null || textFields[i].getText().trim().isEmpty()) {
                button.setDisable(true);
                return;
            }
        }
        button.setDisable(false);
    }
    for (TextField textField : textFields) {
        textField.textProperty().addListener(listener);
    }
}

或者,您可以通过 and 所有条件来构建 BooleanExpression,然后将按钮的 disable 属性绑定(bind)到其否定:

BooleanExpression b = textField1.textProperty().isNotEmpty()
                  .and(textField2.textProperty().isNotEmpty())
                  .and(...);
// b is True if and only if ALL text fields are not-empty. The button should be disabled when this ISN'T the case (enabled when b is True).
button.disableProperty().bind(b.not());

关于java - 在监听器中有效地使用监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44151156/

相关文章:

java - 使用 Paypal API 问题

java - 超越 Java 中的 Integer.MAX_VALUE 约束

JavaFX 折线图 : Insert new data in the middle of the chart

multithreading - 如何避免不在 FX 应用程序线程上; currentThread = JavaFX 应用程序线程错误?

java - 访问在另一个类中创建的对象

java - 队列,优先级如何实现

java - 为什么由返回另一个静态变量的方法调用初始化的静态变量仍然为空?

JavaFX - 通过按钮编辑 TreeView 节点文本

javafx - 如何使此 JavaFX 绑定(bind)多次触发?

JavaFX/TornadoFX 在 MacOS 10.15 (Catalina) 上导致按键接收提示