JavaFX如何检查所有动态添加的文本字段是否为空

JavaFX how to check if all dynamically added textfields are empty

我有一个 TextField 和两个连续的按钮。 一个按钮('add button')添加另一行 TextField 和另一对添加和删除按钮,另一个按钮删除该行。 删除按钮被禁用,而当前行是唯一的行,所以不能没有行。

仅当当前行的文本字段不为空且它是最后一个文本字段时,才会启用添加按钮。所以每一行都有一个禁用的 'add button' 除了最后一行。

我现在的问题是如何将 'add button' disableProperty 绑定到所有存在的文本字段并检查它们是否为空。事实上,我想我只需要检查最后一个文本字段,如果它是空的,我禁用最后一个 'add button' 如果写了最后一个 'add button' 保持禁用但当前行启用。

我找到了一个解决方法,我将按钮绑定到文本字段,然后如果我添加另一行我取消绑定按钮,禁用它,如果我删除一行我只启用最后一个按钮并绑定它反对文本字段。 这个解决方案看起来很笨重,我想知道是否有更优雅的解决方案 属性 绑定。

我的代码(有解决方法,所以你可以看到我想做什么):

public class Controller {
@FXML
private VBox VBox;

public ObservableList<TextField> oList = FXCollections.observableArrayList();
public ObservableList<Button> bList = FXCollections.observableArrayList();

public void initialize(){
    createRow();
}

private void createRow(){
    HBox box = new HBox(10);
    TextField textField = new TextField();
    Button addButton = new Button("Add row");
    Button deleteButton = new Button("Delete");
    box.getChildren().addAll(textField, addButton, deleteButton);
    VBox.getChildren().add(box);

    oList.add(textField);
    bList.add(addButton);

    addButton.disableProperty().bind(Bindings.isEmpty(textField.textProperty()));

    addButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {
            addButton.disableProperty().unbind();
            createRow();
            textField.setDisable(true);
            addButton.setDisable(true);
        }
    });

    deleteButton.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent actionEvent) {

            int idx = oList.indexOf(textField);
            oList.remove(idx);
            bList.remove(idx);
            VBox.getChildren().remove(idx);

            for(TextField tf : oList){
                int i = oList.indexOf(tf);
                if(oList.size()-1 == i){
                    tf.setDisable(false);
                    bList.get(i).disableProperty().bind(Bindings.isEmpty(tf.textProperty()));
                }
            }


        }
    });

}

}

还有两张截图:

添加了 4 行,全部 'add buttons' 禁用,也是最后一行,因为没有在文本字段中写入任何内容

我在这里删除了行 test1 和空行,所有 'add buttons' 仍然被禁用,除了最后一个,因为文本字段中有文本

感谢您的帮助!

PS:我知道在我的代码中 ObservableLists 不是必需的,但我正在尝试并让它们加入,因为我忘记了......

您可以创建一个 BooleanExpression,如果列表中的所有 TextField 都为空,则 returns 为真。请注意,您需要重新创建该表达式作为 ObservableList<TextField> 更改的内容:

oList.addListener((ListChangeListener<? super TextField>) c -> {
    addButton.disableProperty().unbind();
    BooleanExpression allEmpty = oList.stream()
            .map(tf -> BooleanExpression.booleanExpression(tf.textProperty().isEmpty()))
            .reduce(new SimpleBooleanProperty(true), BooleanExpression::and);
    addButton.disableProperty().bind(allEmpty);
});

每次添加或删除新的TextField时,列表中的每个TextField都会映射到empty属性的BooleanExpression TextField。然后,所有的表达式将被加在一起。

注意:同样的方法也可以使用循环而不是流来完成。

注意:您需要在向列表中添加任何元素之前添加此侦听器。