防止JavaFX对话框关闭

16

我目前正在使用JavaFX创建对话框。对话框本身很好用,但现在我正在尝试添加输入验证,在用户忘记填写文本字段时警告用户。我的问题是:是否可以在结果转换器中防止对话框关闭?像这样:

ButtonType buttonTypeOk = new ButtonType("Okay", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(buttonTypeOk);

dialog.setResultConverter((ButtonType param) -> {   

    if (valid()) {
        return ...
    } else {
        Alert alert = new Alert(Alert.AlertType.WARNING);
        alert.setHeaderText("Pleas fill all fields!");
        alert.showAndWait();
        //prevent dialog from closing
    }

});

我注意到如果在结果转换器中抛出错误,则对话框不会关闭,但这似乎不是解决这个问题的好方法。

如果无法通过这种方式解决问题,我可以像这篇文章中所描述的那样禁用按钮。但我更喜欢保持按钮启用并显示一条消息。

提前感谢!

2个回答

28

如何在对话框中进行数据验证的方法已经在Javadoc中有所解释,我引用:

对话框验证/拦截按钮操作

在某些情况下,希望防止对话框关闭直到对话框内的某些方面变得内部一致(例如,对话框内的表单状态都有效)。要做到这一点,对话框API的用户应该熟悉DialogPane.lookupButton(ButtonType)方法。通过传递已经在按钮类型列表中设置过的ButtonType,用户将会得到一个节点,通常是Button类型的(但这取决于是否覆盖了DialogPane.createButton(ButtonType)方法)。使用此按钮,用户可以添加一个事件过滤器,在按钮执行其通常的事件处理之前被调用,并且因此,用户可以通过消耗事件来防止事件处理。以下是一个简化的示例:

final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);
btOk.addEventFilter(
    ActionEvent.ACTION, 
    event -> {
        // Check whether some conditions are fulfilled
        if (!validateAndStore()) {
            // The conditions are not fulfilled so we consume the event
            // to prevent the dialog to close
            event.consume();
        }
    }
);

换句话说,您应该为按钮添加一个事件过滤器,在不满足要求的情况下消耗事件,这将防止对话框被关闭。

更多细节在这里


1
validateAndStore() 方法是什么?它的作用是什么? - Edv Beq
3
@EdvBeq 这个方法并不存在,只是为了表达这个想法而已。它只是一个自定义方法,用于验证输入数据,如果验证成功,则可能会执行其他操作。如果返回true,则对话框将被关闭;否则,事件将被消耗,使得对话框保持打开状态。 - Nicolas Filotto

1
另一种解决方法是使用 setOnCloseRequest,如果您不想仅依赖用户单击“确定”按钮。当有外部请求关闭对话框时,事件处理程序将被调用。然后,事件处理程序可以通过消耗接收到的事件来防止对话框关闭。
    setOnCloseRequest(e ->{
        if(!valid()) {
            e.consume();
        }
    });

我已经尝试了两种解决方案,发现这个更好 - 希望它在未来能得到更多的赞成票... - Martin Frank
这不适用。无论用户按OK还是Cancel按钮,都将触发onCloseRequest。 - Smile

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接