JavaFX TableView 上下文菜单项在 Java 8 上 运行 时出现,直到更新 5,但在以后的更新中不显示

JavaFX TableView Context Menu Item shows up when run on Java 8 until update 5 but not on later ones

下面的代码在 Java 8 update 5 上如其名称所示运行,但在以后的更新上不会运行:

public class TableViewShowingOnlyAnAppendContextMenuItemIfRowIsEmptyElseDeleteIsIncluded extends Application {

private final TableView<Name> table = new TableView<>();
private final ObservableList<Name> data = FXCollections.observableArrayList(new Name("Jacob"),
        new Name("Isabella"), new Name("Ethan"), new Name("Emma"), new Name("Michael"));

public static void main(String[] args) {
    launch(args);
}

@Override
public void start(Stage stage) {

    TableColumn<Name, String> column = new TableColumn<>("Name");
    column.setCellValueFactory(new PropertyValueFactory<>("name"));
    table.getColumns().add(column);
    table.setItems(data);

    ContextMenu contextMenu = new ContextMenu();
    contextMenu.getItems().add(new MenuItem("append"));
    table.setContextMenu(contextMenu);

    table.setRowFactory(tableView -> {
        TableRow<Name> row = new TableRow<>();
        row.contextMenuProperty().bind(
                Bindings.when(Bindings.isNotNull(row.itemProperty()))
                        .then(showOnlyAppendContextMenuItemIfRowIsEmptyElseIncludeDelete())
                        .otherwise((ContextMenu) null));
        return row;
    });

    Scene scene = new Scene(table);
    stage.setScene(scene);
    stage.show();
}

private ContextMenu showOnlyAppendContextMenuItemIfRowIsEmptyElseIncludeDelete() {

    ContextMenu rowMenu = new ContextMenu();
    ContextMenu tableMenu = table.getContextMenu();
    if (tableMenu != null)
        rowMenu.getItems().addAll(tableMenu.getItems());
    rowMenu.getItems().add(new MenuItem("delete"));
    return rowMenu;
}

public static class Name {

    private final SimpleStringProperty name;

    private Name(String name) {
        this.name = new SimpleStringProperty(name);
    }

    public String getName() {
        return name.get();
    }

    public void setName(String name) {
        this.name.set(name);
    }
} }

能帮我找出代码中的错误吗?或者如果有none,这是应该提交的回归吗?截至目前,所有使用的PC都是8u5。

提前致谢。

此代码看起来像是我前一段时间发布的内容...

问题是不真正支持在多个菜单中使用 MenuItem。虽然这在 Javadocs 中没有明确说明,但 MenuItem 有一个 getMenu() 方法这一事实确实暗示了这一点。事实上,它在 8u5 之前工作真的只是运气......

解决方法是创建新的菜单项,它们是 table 的上下文菜单中菜单项的副本:

private ContextMenu showOnlyAppendContextMenuItemIfRowIsEmptyElseIncludeDelete() {

    ContextMenu rowMenu = new ContextMenu();
    ContextMenu tableMenu = table.getContextMenu();

    if (tableMenu != null) {
        for (MenuItem item : tableMenu.getItems()) {
            MenuItem rowItem = new MenuItem(item.getText());
            rowItem.setGraphic(item.getGraphic());
            rowItem.setOnAction(item.getOnAction());
            rowMenu.getItems().add(rowItem);
        }

    }

    rowMenu.getItems().add(new MenuItem("delete"));
    return rowMenu;
}

另一种方法是使用 ControlsFX 动作,因此您可以为整个 table 维护一个(单个)动作列表,并从中为 table 和行生成菜单项。