JavaFX对话框的问题

时间:2017-10-05 06:52:03

标签: javafx java-8 javafx-8

我有一个带有主窗口的JavaFX应用程序。点击"创建用户"按钮,显示一个对话框以获取用户的输入。在" OK"之后单击对话框上的按钮,禁用对话框并将光标更改为等待,同时应用程序执行创建新用户的必要任务。如果任务成功,将关闭对话框,并显示信息警报以宣布成功。

以下是我从实际代码中简化的代码,以重现我遇到的问题。以下是问题:

  1. 为什么dialog.getDialogPane()。setCursor(Cursor.WAIT)不起作用?我可以使用primaryStage.getScene()。setCursor(Cursor.WAIT)更改主窗口上的光标。但是如何更改对话框上的光标?

  2. 当显示警报时,即使在显示警报之前调用了dialog.close(),似乎也无法关闭对话框(但是,如果我只用一个按钮就可以简化对话框,没有别的,当我调用dialog.close()时它会消失。此外,当我拖动警告框时,对话框及其后面的主窗口不会刷新。所以似乎代码不对。

  3. 代码:

    import javafx.application.Application;
    import javafx.concurrent.Task;
    import javafx.event.ActionEvent;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Cursor;
    import javafx.scene.Scene;
    import javafx.scene.control.Alert;
    import javafx.scene.control.Button;
    import javafx.scene.control.ButtonType;
    import javafx.scene.control.Dialog;
    import javafx.scene.control.Label;
    import javafx.scene.control.PasswordField;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.TextField;
    import javafx.scene.control.Alert.AlertType;
    import javafx.scene.layout.GridPane;
    import javafx.scene.layout.VBox;
    import javafx.scene.text.Text;
    import javafx.stage.Stage;
    
    public class Demo extends Application {
    
        private Dialog<String> dialog;
        private Button createUserButton = new Button("Create User");
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            Text usersLabel = new Text("Current Users:");
            TableColumn<User, String> indexColumn = new TableColumn<User, String>("No.");
            indexColumn.setMaxWidth(1f * Integer.MAX_VALUE * 10);
            indexColumn.setCellValueFactory(p -> p.getValue().indexProperty());
            TableColumn<User, String> userNameColumn = new TableColumn<User, String>("User Name");
            userNameColumn.setMaxWidth(1f * Integer.MAX_VALUE * 60);
            userNameColumn.setCellValueFactory(p -> p.getValue().userNameProperty());
            TableColumn<User, String> roleColumn = new TableColumn<User, String>("Role");
            roleColumn.setMaxWidth(1f * Integer.MAX_VALUE * 30);
            roleColumn.setCellValueFactory(p -> p.getValue().roleProperty());
            TableView<User> tableView = new TableView<User>();
            tableView.getColumns().add(indexColumn);
            tableView.getColumns().add(userNameColumn);
            tableView.getColumns().add(roleColumn);
            tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            Text dummyLabel = new Text("");
            createUserButton.setOnAction(event -> showDialog());
            VBox leftPane = new VBox(5);
            leftPane.getChildren().addAll(usersLabel, tableView);
            VBox rightPane = new VBox(20);
            rightPane.setFillWidth(true);
            rightPane.getChildren().addAll(dummyLabel, createUserButton);
            GridPane mainPane = new GridPane();
            mainPane.setPadding(new Insets(10, 0, 0, 10));
            mainPane.setHgap(20);
            mainPane.add(leftPane, 0, 0);
            mainPane.add(rightPane, 1, 0);
            Scene scene = new Scene(mainPane);
            primaryStage.setScene(scene);
            primaryStage.setResizable(false);
            primaryStage.show();
        }
    
        private void showDialog() {
            dialog = new Dialog<>();
            dialog.setTitle("Create User");
            dialog.setHeaderText("Please enter User Name and Password to create a new user.");
            dialog.setResizable(false);
            Label userNameLabel = new Label("User Name:");
            Label passwordLabel = new Label("Password:");
            TextField userNameField = new TextField();
            PasswordField passwordField = new PasswordField();
            GridPane grid = new GridPane();
            grid.setAlignment(Pos.CENTER);
            grid.setHgap(10);
            grid.setVgap(10);
            grid.setPadding(new Insets(20, 35, 20, 35));
            grid.add(userNameLabel, 1, 1);
            grid.add(userNameField, 2, 1);
            grid.add(passwordLabel, 1, 2);
            grid.add(passwordField, 2, 2);
            dialog.getDialogPane().setContent(grid);
            dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
            Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
            okButton.addEventFilter(ActionEvent.ACTION, event -> {
                createUser(userNameField.getText().trim(), passwordField.getText());
                event.consume();
            });
            dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
            dialog.showAndWait();
        }
    
        private void createUser(String userName, String password) {
            dialog.getDialogPane().setDisable(true);
            dialog.getDialogPane().setCursor(Cursor.WAIT); // does not work!
            Task<Boolean> task = new Task<Boolean>() {
                @Override
                public Boolean call() {
                    try {
                        Thread.sleep(2000); // simulate processing
                    } catch (InterruptedException exception) {
                    }
                    return Boolean.TRUE;
                }
            };
            task.setOnSucceeded(e -> {
                Boolean success = task.getValue();
                dialog.getDialogPane().setDisable(false);
                dialog.getDialogPane().setCursor(Cursor.DEFAULT);
                if (success.booleanValue()) {
                    dialog.close(); // does not seem to close before alert is shown
                    Alert alert = new Alert(AlertType.INFORMATION);
                    alert.setTitle("Create User Successful");
                    alert.setHeaderText("The user is successfully created.");
                    alert.showAndWait();
                } else {
                    Alert alert = new Alert(AlertType.ERROR);
                    alert.setTitle("Create User Error");
                    alert.setHeaderText("Unable to create user.");
                    alert.showAndWait();
                }
            });
            new Thread(task).start();
        }
    
        public static void main(String[] arguments) {
            Application.launch(arguments);
        }
    
    }
    

    以下是User类的代码:

    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    
    public class User {
    
        private StringProperty index;
    
        private StringProperty userName;
    
        private StringProperty role;
    
        public void setIndex(String index) {
            indexProperty().set(index);
        }
    
        public String getIndex() {
            return indexProperty().get();
        }
    
        public StringProperty indexProperty() {
            if (index == null) {
                index = new SimpleStringProperty(this, "index");
            }
            return index;
        }
    
        public void setUserName(String userName) {
            userNameProperty().set(userName);
        }
    
        public String getUserName() {
            return userNameProperty().get();
        }
    
        public StringProperty userNameProperty() {
            if (userName == null) {
                userName = new SimpleStringProperty(this, "userName");
            }
            return userName;
        }
    
        public void setRole(String role) {
            roleProperty().set(role);
        }
    
        public String getRole() {
            return roleProperty().get();
        }
    
        public StringProperty roleProperty() {
            if (role == null) {
                role = new SimpleStringProperty(this, "role");
            }
            return role;
        }
    
    }
    

    编辑:

    (1)对于光标问题,我只需要改变这一行:

    dialog.getDialogPane().setCursor(Cursor.WAIT);
    

    为:

    dialog.getDialogPane().getScene().setCursor(Cursor.WAIT)
    

    (2)对于第二个问题,我只需要改变这一行:

    dialog.close();
    

    为:

    Platform.runLater(() -> {
        dialog.close();
    });
    

    解决方案:

    import javafx.application.Application;
    import javafx.application.Platform;
    import javafx.concurrent.Task;
    import javafx.event.ActionEvent;
    import javafx.geometry.Insets;
    import javafx.geometry.Pos;
    import javafx.scene.Cursor;
    import javafx.scene.Scene;
    import javafx.scene.control.Alert;
    import javafx.scene.control.Button;
    import javafx.scene.control.ButtonType;
    import javafx.scene.control.Dialog;
    import javafx.scene.control.Label;
    import javafx.scene.control.PasswordField;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.scene.control.TextField;
    import javafx.scene.control.Alert.AlertType;
    import javafx.scene.layout.GridPane;
    import javafx.scene.layout.VBox;
    import javafx.scene.text.Text;
    import javafx.stage.Stage;
    
    public class Demo extends Application {
    
        private Dialog<String> dialog;
        private Button createUserButton = new Button("Create User");
    
        @Override
        public void start(Stage primaryStage) throws Exception {
            Text usersLabel = new Text("Current Users:");
            TableColumn<User, String> indexColumn = new TableColumn<User, String>("No.");
            indexColumn.setMaxWidth(1f * Integer.MAX_VALUE * 10);
            indexColumn.setCellValueFactory(p -> p.getValue().indexProperty());
            TableColumn<User, String> userNameColumn = new TableColumn<User, String>("User Name");
            userNameColumn.setMaxWidth(1f * Integer.MAX_VALUE * 60);
            userNameColumn.setCellValueFactory(p -> p.getValue().userNameProperty());
            TableColumn<User, String> roleColumn = new TableColumn<User, String>("Role");
            roleColumn.setMaxWidth(1f * Integer.MAX_VALUE * 30);
            roleColumn.setCellValueFactory(p -> p.getValue().roleProperty());
            TableView<User> tableView = new TableView<User>();
            tableView.getColumns().add(indexColumn);
            tableView.getColumns().add(userNameColumn);
            tableView.getColumns().add(roleColumn);
            tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
            Text dummyLabel = new Text("");
            createUserButton.setOnAction(event -> showDialog());
            VBox leftPane = new VBox(5);
            leftPane.getChildren().addAll(usersLabel, tableView);
            VBox rightPane = new VBox(20);
            rightPane.setFillWidth(true);
            rightPane.getChildren().addAll(dummyLabel, createUserButton);
            GridPane mainPane = new GridPane();
            mainPane.setPadding(new Insets(10, 0, 0, 10));
            mainPane.setHgap(20);
            mainPane.add(leftPane, 0, 0);
            mainPane.add(rightPane, 1, 0);
            Scene scene = new Scene(mainPane);
            primaryStage.setScene(scene);
            primaryStage.setResizable(false);
            primaryStage.show();
        }
    
        private void showDialog() {
            dialog = new Dialog<>();
            dialog.setTitle("Create User");
            dialog.setHeaderText("Please enter User Name and Password to create a new user.");
            dialog.setResizable(false);
            Label userNameLabel = new Label("User Name:");
            Label passwordLabel = new Label("Password:");
            TextField userNameField = new TextField();
            PasswordField passwordField = new PasswordField();
            GridPane grid = new GridPane();
            grid.setAlignment(Pos.CENTER);
            grid.setHgap(10);
            grid.setVgap(10);
            grid.setPadding(new Insets(20, 35, 20, 35));
            grid.add(userNameLabel, 1, 1);
            grid.add(userNameField, 2, 1);
            grid.add(passwordLabel, 1, 2);
            grid.add(passwordField, 2, 2);
            dialog.getDialogPane().setContent(grid);
            dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
            Button okButton = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
            okButton.addEventFilter(ActionEvent.ACTION, event -> {
                createUser(userNameField.getText().trim(), passwordField.getText());
                event.consume();
            });
            dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
            dialog.showAndWait();
        }
    
        private void createUser(String userName, String password) {
            dialog.getDialogPane().setDisable(true);
            dialog.getDialogPane().getScene().setCursor(Cursor.WAIT); // Changed
            Task<Boolean> task = new Task<Boolean>() {
                @Override
                public Boolean call() {
                    try {
                        Thread.sleep(2000); // simulate processing
                    } catch (InterruptedException exception) {
                    }
                    return Boolean.TRUE;
                }
            };
            task.setOnSucceeded(e -> {
                Boolean success = task.getValue();
                dialog.getDialogPane().setDisable(false);
                dialog.getDialogPane().getScene().setCursor(Cursor.DEFAULT); // Changed
                if (success.booleanValue()) {
                    Platform.runLater(() -> { // Added
                        dialog.close();
                    });                       // Added
                    Alert alert = new Alert(AlertType.INFORMATION);
                    alert.setTitle("Create User Successful");
                    alert.setHeaderText("The user is successfully created.");
                    alert.showAndWait();
                } else {
                    Alert alert = new Alert(AlertType.ERROR);
                    alert.setTitle("Create User Error");
                    alert.setHeaderText("Unable to create user.");
                    alert.showAndWait();
                }
            });
            new Thread(task).start();
        }
    
        public static void main(String[] arguments) {
            Application.launch(arguments);
        }
    
    }
    

2 个答案:

答案 0 :(得分:0)

你的问题来自这行代码:

dialog.getDialogPane().setDisable(true);

不要停用DialogPane,只需停用Node上的Pane

您似乎提出了多个问题。这会回答您的Cursor问题。

答案 1 :(得分:0)

您仍然可以停用DialogPane。但是,我认为通过禁用DialogPane,您也可以防止它受到重击测试,从而阻止接收任何鼠标事件。

但您可以使用dialog.getDialogPane().setDisable(true); dialog.getDialogPane().getScene().setCursor(Cursor.WAIT); 的任何父节点(本例中为场景节点):

toString()