我正在开发一个自定义的TreeView对象.我使用一个自定义的cellFactory来提供我的TreeView的TreeCell对象.这允许我在不同的单元格上安装自定义的上下文菜单,这取决于它们所显示的项目。
但我对这种行为并不完全满意。
当左键点击单元格时,它被选中(OK)但是当右键点击单元格时,上下文菜单被显示(OK)但是单元格也被选中。(NOK)
我怎样才能改变这种行为?
我试着在树形视图上实现一个事件过滤,如果是右键点击,则消耗该事件,但这并没有改变任何东西,上述行为仍然适用。
addEventFilter(MouseEvent.MOUSE_CLICKED,
new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.getButton() == MouseButton.SECONDARY) {
event.consume();
}
}
});
setCellFactory(new Callback<TreeView<TreeDisplayable>, TreeCell<TreeDisplayable>>() {
@Override
public TreeCell<TreeDisplayable> call(
final TreeView<TreeDisplayable> treeView) {
return new TreeDisplayableTreeCell(owner, javaModel);
}
});
public class TreeDisplayableTreeCell extends TreeCell<TreeDisplayable> {
...
@Override
public void updateItem(TreeDisplayable item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
setText(getItem().treeViewString());
setGraphic(item.getPic());
if (getTreeItem().getParent() == null) {
// it means it's the root node
setContextMenu(new RootItemContextMenu(javaModel, owner));
} else {
setContextMenu(new TreeItemContextMenu(javaModel, owner,getTreeItem().getValue()));
}
}
}
}
对Tony的评论作出反应
创建一个自定义的EventDispatcher可以做到这一点。
public class TreeEventDispatcher implements EventDispatcher {
@Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
if (event instanceof MouseEvent) {
MouseEvent mouseEvent = (MouseEvent) event;
if (mouseEvent.getButton() == MouseButton.SECONDARY) {
event.consume();
} else {
event = tail.dispatchEvent(event);
}
} else {
event = tail.dispatchEvent(event);
}
return event;
}
}
除了右键事件外,所有事件的行为都是相同的,因为右键事件被消耗了,从而阻止了对任何TreeCell的右键选择。
幸运的是,右键单击时仍然显示上下文菜单(尽管我不明白为什么......)。有人有什么线索吗?
上一个 Facewindu 答案实际上是可行的,但还有另一种方法可以实现这种行为,并且在右键单击时仍有上下文菜单出现。
treeView.addEventFilter(MOUSE_PRESSED, event -> {
if (event.isSecondaryButtonDown()) {
Node text = (Node) event.getTarget();
TreeCell<...> treeCell = (TreeCell<...>) text.getParent();
treeCell.getContextMenu().show(treeCell, 0, 0);
event.consume();
}
});