有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案