我试图在表格列的上下文菜单中放置一些节点控件。但是,当我右键单击表头以触发ContextMenu时,它会将左上角放在光标位置上。有没有一种简单的方法可以将ContextMenu的左上角锚定到TableHeader的左下角?我无法在TableView的属性中的任何位置找到表头。
ContextMenu contextMenu = new ContextMenu();
contextMenu.setAnchorLocation(... what do I anchor to?);
contextMenu.getItems().add(FilterPanel.getInMenuItem(this));
tableColumn.setContextMenu(contextMenu);
此外,有没有办法允许用户通过拖动来调整ContextMenu的大小?
答案 0 :(得分:2)
不幸的是,对于我的解决方案,我不得不深入研究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;
}
基本上我们在这里做的是:
TableColumn
ContextMenu
从鼠标坐标绝对定位到TableColumnHeader皮肤下方相对位置的行为。