【问题标题】:Howto make JavaFX Dialog NOT closing itself after pressing OK Button按下确定按钮后如何使 JavaFX 对话框不自行关闭
【发布时间】:2016-07-06 17:55:49
【问题描述】:

目前我正在使用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();
    }

【问题讨论】:

    标签: java javafx dialog


    【解决方案1】:

    来自Dialog API Documentation

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

    在某些情况下,最好防止对话框关闭 直到对话的某些方面变得内部一致(例如 对话框内的表单的所有字段都处于有效状态)。去做这个, 对话 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 这是个人喜好问题 :-) 所以这篇文章对其他搜索相同内容的人很有帮助。请将其标记为答案(绿色钩子),谢谢。
    • 是的 :) 你是完全正确的。刚刚把你和绿色联系起来,期待这篇文章能帮助有需要的人!
    猜你喜欢
    • 2017-04-12
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多