JavaFX 8-将 TableView 列 ContextMenu 锚定在列标题的正下方?

标签 javafx tableview javafx-8

我试图将一些节点控件放入表列的上下文菜单中。但是,当我右键单击表标题以触发上下文菜单时,它将左上角放在光标位置上。有没有一种简单的方法可以将 ContextMenu 的左上角锚定到 TableHeader 的左下角?我在 TableView 属性中的任何位置都找不到表头。

ContextMenu contextMenu = new ContextMenu();
contextMenu.setAnchorLocation(... what do I anchor to?);

contextMenu.getItems().add(FilterPanel.getInMenuItem(this));
tableColumn.setContextMenu(contextMenu);

另外,有没有办法允许用户通过拖动来调整 ContextMenu 的大小?

最佳答案

不幸的是,对于我的解决方案,我必须深入研究 TableView 的皮肤。

首先,我们必须注册 TableView 的皮肤,因此一旦设置完成,我们就会收到通知:

tableView.skinProperty().addListener((w, o, n) -> {
    if (n instanceof TableViewSkin) {
        TableViewSkin<?> skin = (TableViewSkin<?>) n;
            checkChangeContextMenu(skin, column);
    }
});

其次我们有神奇的代码:

private static void checkChangeContextMenu(TableViewSkin<?> skin, TableColumn<?, ?> column) {
    NestedTableColumnHeader header = skin.getTableHeaderRow()
            .getRootHeader();
    header.getColumnHeaders().addListener((Observable obs) -> changeContextMenu(header,column));
    changeContextMenu(header, column);
}

private static void changeContextMenu(NestedTableColumnHeader header, TableColumn<?, ?> column) {
    TableColumnHeader headerSkin = scan(column, header);
    if (headerSkin != null) {
        headerSkin.setOnContextMenuRequested(ev -> {
            ContextMenu cMenu = column.getContextMenu();
            if (cMenu != null) {
                cMenu.show(headerSkin, Side.BOTTOM, 5, 5);
            }
            ev.consume();
        });
    }
}

private static TableColumnHeader scan(TableColumn<?, ?> search,
        TableColumnHeader header) {
    // firstly test that the parent isn't what we are looking for
    if (search.equals(header.getTableColumn())) {
        return header;
    }

    if (header instanceof NestedTableColumnHeader) {
        NestedTableColumnHeader parent = (NestedTableColumnHeader) header;
        for (int i = 0; i < parent.getColumnHeaders().size(); i++) {
            TableColumnHeader result = scan(search, parent
                    .getColumnHeaders().get(i));
            if (result != null) {
                return result;
            }
        }
    }

    return null;
}

本质上我们在这里所做的事情:

  1. 注册 TableHeader 皮肤更新
  2. 搜索 TableColumn 的皮肤
  3. ContextMenu 的显示方式从鼠标坐标的绝对定位更改为 TableColumnHeader 皮肤下方的相对定位。

关于JavaFX 8-将 TableView 列 ContextMenu 锚定在列标题的正下方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27696578/

相关文章:

java - RichTextFX 的撤消功能无法正常工作

javafx - 鼠标沿 javafx 中的 Z 轴旋转

javafx-2 - 数据库操作的任务与服务

JavaFX如何将对话框/警报带到屏幕前面

JavaFx TreeTableCell 宽度计算

java - 异步建立连接

javafx canvas draw 与 java.awt.graphics2d draw 的比较

iOS如何有效地将UIView添加到tableview单元格

ios - 添加第一个项目时(以及删除最后一个项目时)tableView 崩溃

JavaFX 将组合框中的字符串字段显示为字符串的枚举(在 TableView 中)