java JavaFX在单击显示阻塞对话框的上下文菜单项后挂起
我设计了一个TableView
,用户可以右键单击任何一行,它会显示一些与所选TableRow
相关的选项
TableView<MyObservable> table = new TableView<>();
table.setRowFactory(tv -> {
TableRow<MyObservable> row = new TableRow<>();
row.setOnMouseClicked(new StoredSessionListener(LOGIN_STAGE, table, row));
return row;
});
StoredSessionListener
具有从构造函数调用的以下方法:
private final void attachContextMenuOnRow() {
ContextMenu contextMenuOnRow = new ContextMenu();
contextMenuOnRow.getItems().add(getRemoveAction());
// Rest of the items ommitted
row.setContextMenu(contextMenuOnRow);
}
private MenuItem getRemoveAction() {
MenuItem removeSessionItem = new MenuItem("Remove Session");
removeSessionItem.setOnAction((action) -> {
try {
ButtonType type = super.showBlockingDialog(Alert.AlertType.CONFIRMATION, "Delete", "Delete", "Delete");
// Do stuff according to user button type
} catch (Exception ex) {
ex.printStackTrace();
}
});
return removeSessionItem;
}
showBlockingDialog()
是在侦听器正在扩展的一个类中实现的方法
protected ButtonType showBlockingDialog(
final AlertType type,
final String dialogTitle,
final String dialogHeader,
final String dialogMessage) throws Exception {
Objects.requireNonNull(type);
final FutureTask<ButtonType> dialog = new FutureTask(() -> {
final var alert = new Alert(type);
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
alert.setResizable(false);
alert.setTitle(dialogTitle);
alert.setHeaderText(dialogHeader);
alert.setContentText(dialogMessage);
var buttonType = alert.showAndWait().get();
alert.close();
return buttonType;
});
Platform.runLater(dialog);
return dialog.get();
}
右键单击该行将显示上下文菜单,但选择Remove MenuItem选项将导致应用程序无一例外地挂起。不显示任何对话框
我已经跟踪了这个案例,我认为错误发生在return dialog.get()
行,但是我在另一个操作(第showBlockingDialog
部分)上使用了相同的代码,没有问题
---编辑最小示例
public class App extends Application {
@Override
public void start(Stage stage) {
TableView tableView = new TableView();
TableColumn nameColumn = new TableColumn("Name");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
tableView.setRowFactory(tv -> {
TableRow<Item> row = new TableRow<>();
row.setOnMouseClicked((event) -> {
ContextMenu menu = new ContextMenu();
MenuItem remove = new MenuItem("Remove");
remove.setOnAction((action) -> {
try {
ButtonType selectedButtonType = showBlockingDialog(AlertType.CONFIRMATION, "Remove");
System.out.println("Selected: " + selectedButtonType);
} catch (Exception ex) {
ex.printStackTrace();
}
});
menu.getItems().add(remove);
row.setContextMenu(menu);
});
return row;
});
tableView.setItems(FXCollections.observableList(Arrays.asList(new Item())));
tableView.getColumns().addAll(nameColumn);
var scene = new Scene(new StackPane(tableView), 640, 480);
stage.setScene(scene);
stage.show();
}
protected ButtonType showBlockingDialog(final AlertType type, final String dialogTitle) throws Exception {
Objects.requireNonNull(type);
final FutureTask<ButtonType> dialog = new FutureTask(
new BlockingDialog(type, dialogTitle)
);
Platform.runLater(dialog);
return dialog.get();
}
public static void main(String[] args) {
launch();
}
public static class BlockingDialog implements Callable<ButtonType> {
private final AlertType type;
private final String dialogTitle;
public BlockingDialog(AlertType type, String dialogTitle) {
this.type = type;
this.dialogTitle = dialogTitle;
}
@Override
public ButtonType call() throws Exception {
var alert = new Alert(type);
alert.setTitle(dialogTitle);
var buttonType = alert.showAndWait().get();
alert.close();
return buttonType;
}
}
public static class Item {
private final String name;
private final StringProperty nameProperty;
public Item() {
this.name = UUID.randomUUID().toString();
this.nameProperty = new SimpleStringProperty(this.name);
}
public StringProperty nameProperty() {
return nameProperty;
}
}
}
共 (0) 个答案