我有一个带有主窗口的JavaFX应用程序。点击"创建用户"按钮,显示一个对话框以获取用户的输入。在" OK"之后单击对话框上的按钮,禁用对话框并将光标更改为等待,同时应用程序执行创建新用户的必要任务。如果任务成功,将关闭对话框,并显示信息警报以宣布成功。
以下是我从实际代码中简化的代码,以重现我遇到的问题。以下是问题:
为什么dialog.getDialogPane()。setCursor(Cursor.WAIT)不起作用?我可以使用primaryStage.getScene()。setCursor(Cursor.WAIT)更改主窗口上的光标。但是如何更改对话框上的光标?
当显示警报时,即使在显示警报之前调用了dialog.close(),似乎也无法关闭对话框(但是,如果我只用一个按钮就可以简化对话框,没有别的,当我调用dialog.close()时它会消失。此外,当我拖动警告框时,对话框及其后面的主窗口不会刷新。所以似乎代码不对。
代码:
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);
}
}
答案 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()