Issue
I am writting a little desktop application with a TreeView according to the Oracle-Example from here: https://docs.oracle.com/javafx/2/ui_controls/tree-view.htm.
From a MenuItem action of a ContextMenu, I would like to fire an event which shall create a new TreeItem below the item where I opened the ContextMenu from.
For MenuItem, it is possible to use the setOnAction(EventHandler<ActionEvent> event)
method, but I only want to fire the action from a left mouse-click.
First, it is not possible to add an EventHandler to a MenuItem although it provides the method addEventHandler(EventType type, EventHandler<EventType> handler)
with the event-type MouseEvent.ANY (or anything else). The handle-method of the event-handler is not called.
Second, i can use a workarround by adding a Label to a MenuItem by menuItem.setGraphic(label)
and add an EventHandler to the label. This one works although MouseEvent.MOUSE_CLICKED
is not called by an EventHandler's handle-method on a Label.
Is this "normal" behaviour? I understand that a label does not react on a click-event, but I do not understand why it is not possible to register a separate EventHandler or EventFilter on a MenuItem.
Solution
ContextMenu
uses a MenuItemContainer
, which is a
Container responsible for laying out a single row in the menu - in other words, this contains and lays out a single MenuItem, regardless of it's specific subtype.
Fur this purpose it seems to create new Nodes
representing the MenuItem
. So any EventHandlers
added to the MenuItem
will not be called.
To make it work as you intended, you can use a CustomMenuItem
and add the according EventHandler
to its content
:
public class ContextMenuCell extends TreeCell<String> {
private ContextMenu menu;
public ContextMenuCell() {
Label lbl = new Label("Add item");
MenuItem menuItem = new CustomMenuItem(lbl);
lbl.setOnMouseClicked(evt -> {
if (evt.getButton() != MouseButton.PRIMARY) {
return;
}
TreeItem treeItem =
new TreeItem<String>("New item");
if (getTreeItem().isLeaf()) {
getTreeItem().getParent().getChildren().add(getIndex(), treeItem);
} else {
getTreeItem().getChildren().add(0, treeItem);
}
});
menu = new ContextMenu(menuItem);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
setText(item);
setGraphic(getTreeItem().getGraphic());
setContextMenu(menu);
}
}
}
Answered By - jns
Answer Checked By - Mary Flores (JavaFixing Volunteer)