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

时间:2016-07-06 17:55:49

标签: 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();
            }
        });

解释: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();
    }

1 个答案:

答案 0 :(得分:5)

来自Dialog API Documentation

  

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

     

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

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