按OK按钮后如何使JavaFX Dialog不关闭

Chi*_*ddi 1 java dialog javafx

目前我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();
            }
        });
Run Code Online (Sandbox Code Playgroud)

说明:eventfilter捕获任何不匹配的密码,并向标签节点发送错误消息以进行通知.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();
    }
Run Code Online (Sandbox Code Playgroud)

aw-*_*ink 5

Dialog 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();
     }
 });
Run Code Online (Sandbox Code Playgroud)