java - 如何使 JavaFX 对话框在按下 OK 按钮后不自行关闭

标签 java javafx dialog

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

最佳答案

来自Dialog API Documentation :

Dialog Validation / Intercepting Button Actions

In some circumstances it is desirable to prevent a dialog from closing until some aspect of the dialog becomes internally consistent (e.g. a form inside the dialog has all fields in a valid state). To do this, users of the dialogs API should become familiar with the DialogPane.lookupButton(ButtonType) method. By passing in a ButtonType (that has already been set in the button types list), users will be returned a Node that is typically of type Button (but this depends on if the DialogPane.createButton(ButtonType) method has been overridden). With this button, users may add an event filter that is called before the button does its usual event handling, and as such users may prevent the event handling by consuming the event. Here's a simplified example:

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

关于java - 如何使 JavaFX 对话框在按下 OK 按钮后不自行关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38230632/

相关文章:

java - type[] varName 和 type varName[] 的区别?

java - 有没有办法在 Java 中实现代数类型?

JavaFX:禁用使用键盘控制 RadioButtons

dialog - 如何使用 WIX 自定义对话框窗口图标?

android - 无法添加窗口—— token android.os.BinderProxy@42824 无效;你的 Activity 在运行吗?

android - 对话框布局双层错误透明背景

java - 我如何开始在 Eclipse 中设计 portlet?

java - 如何在 Redis 中存储值列表?

java - 如何更改按钮阵列上的数字?

JavaFX:更改以编程方式创建的按钮值的方法