如何使JavaFX对话框在按下“确定”按钮后不关闭自身

3

目前我正在使用Dialog<User> loginDialog = new Dialog<>();来创建一个登录对话框,在该对话框中,用户需要输入用户名和密码,然后点击“确认”按钮进行登录。

我的问题

不幸的是,每次按下“确认”按钮时,对话框面板都会自动关闭,无论登录是否成功。我希望只有在取消按钮被按下或者登录成功时才关闭对话框面板。

解决方案

正如NwDX所指出的那样,需要使用addEventFilter方法。我的实现看起来像这样:

btnLogin.addEventFilter(ActionEvent.ACTION, event -> {
            if (!comboAdministrator.getValue().getPassword().equals(pfLogin.getText())) {
                lblErrorNotification.setText("Password is incorrect. Try again!");
                pfLogin.requestFocus();
                event.consume();
            }
        });

解释:事件过滤器会捕获任何不匹配的密码,并将错误消息发送到标签节点以进行通知。event.consume()是必要的,否则对话框将再次关闭并恢复其原始行为。

完整代码解决方案

private Optional<User> showLoginDialog() {

        Dialog<User> dialog = new Dialog<>();
        dialog.setTitle("Administrator Login");
        dialog.setHeaderText("Enter administrator password");
        dialog.initOwner(btnShowManagerView.getScene().getWindow());
        dialog.getDialogPane().getStylesheets().add("util/resources/myCSS.css");

        dialog.setGraphic(new ImageView(ResourceClass.class.getResource("locker.png").toString()));

        ButtonType loginButtonType = new ButtonType("Login", ButtonData.YES);
        ButtonType cancelButtonType = ButtonType.CANCEL;

        dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, cancelButtonType);

        Label lblErrorNotification = new Label();
        lblErrorNotification.setTextFill(Color.RED);

        GridPane gridPane = new GridPane();
        gridPane.setHgap(10);
        gridPane.setVgap(10);
        gridPane.setPadding(new Insets(20, 150, 20, 20));

        ComboBox<User> comboAdministrator = new ComboBox();
        comboAdministrator.setItems(main.getAdministrators());
        comboAdministrator.setValue(main.getAdministrators().get(0));
        comboAdministrator.setConverter(new StringConverter<User>() {

            @Override
            public String toString(User object) {
                return object.getLoginName();
            }

            @Override
            public User fromString(String string) {
                return null;
            }
        });
        main.enableComboBoxBaseShowIfFocused(comboAdministrator);

        PasswordField pfLogin = new PasswordField();

        gridPane.add(new Label("AdminUser"), 0, 0);
        gridPane.add(comboAdministrator, 1, 0);
        gridPane.add(new Label("Password"), 0, 1);
        gridPane.add(pfLogin, 1, 1);
        gridPane.add(lblErrorNotification, 1, 2);

        Button btnLogin = (Button) dialog.getDialogPane().lookupButton(loginButtonType);

        btnLogin.addEventFilter(ActionEvent.ACTION, event -> {
            if (!comboAdministrator.getValue().getPassword().equals(pfLogin.getText())) {
                lblErrorNotification.setText("Password is incorrect. Try again!");
                pfLogin.requestFocus();
                event.consume();
            }
        });

        btnLogin.disableProperty()
                .bind(pfLogin.textProperty().isEmpty());

        dialog.getDialogPane().setContent(gridPane);

        Platform.runLater(()
                -> comboAdministrator.requestFocus());

        dialog.setResultConverter((ButtonType buttonType) -> {
            if (buttonType == loginButtonType) {
                return comboAdministrator.getValue();
            }

            return null;
        });

        return dialog.showAndWait();
    }
1个回答

7
来自对话框API文档:

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

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

 final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);
 btOk.addEventFilter(ActionEvent.ACTION, event -> {
     if (!validateAndStore()) {
         event.consume();
     }
 });

你好,非常感谢你的努力。我从你那里学到了下一次在向社区提问之前应该自己仔细阅读Java API文档。 - Chiggiddi
@Chiggiddi 这是一件看个人喜好的事情 :-) 所以这篇帖子有助于其他搜索同样问题的人。请将其标记为答案(绿色勾),谢谢。 - aw-think
没错 :) 你说得完全正确。我已经为你点了个赞,期待这篇文章能帮助到其他需要帮助的人! - Chiggiddi

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