Reputation: 173
I am writing a javafx UI and would like to get the owner Node of a contextMenu from a eventHandler for the MenuItem that was clicked on.
My Code:
TabPane tabPane = new TabPane();
Tab tab1 = new Tab();
Tab tab2 = new Tab();
tabPane.getTabs().addAll(tab1,tab2);
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Do Some Action");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
@override
public void handle(ActionEvent e){
// Get the tab which was clicked on and do stuffs with it
}
});
contextMenu.getItems().add(menuItem);
for(Tab tab: tabPane.getTabs()){
tab.setContextMenu(contextMenu);
}
What I would like to do is get a reference to the tab that had it's contextMenu selected.
I was able to get a reference to what appears to be the ContextMenu of the MenuItem with the following code inside of the handle(ActionEvent e) method for the menuItem eventHandler:
ContextMenu menu = ((ContextMenu)((MenuItem)e.getSource()).getParentPopup());
My idea from there was to use ContextMenu's .getOwnerNode() method on menu and then have a reference to the tab, but when running that I get a reference to an item that I can't make sense of.
The toString() method for the object returned by .getOwnerNode() returns "TabPaneSkin$TabHeaderSkin$3@14f59cef" which I can't figure out the meaning of.
Is my approach of trying to work my way up the chain until I get to the node correct or is there an entirely different approach that will work better?
All I need to have is the functionality of a ContextMenu, and when the MenuItem is clicked on, I need to have a reference to the tab for which the ContextMenu was selected so I can do cool stuffs with it.
Upvotes: 4
Views: 3542
Reputation: 159566
Here is a code snippet:
final Tab tab = new Tab("xyzzy");
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Do Some Action");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
@Override public void handle(ActionEvent e){
tab.setText("Activated by User");
}
});
Every time the user right clicks on a tab header and selects the "Count Click" menu, the content of the related tab is updated with a count of the number of licks counted so far for that tab.
Here is an executable sample:
import javafx.application.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class TabContext extends Application {
@Override public void start(Stage stage) {
TabPane tabPane = new TabPane();
tabPane.getTabs().addAll(
createTab("xyzzy", "aliceblue"),
createTab("frobozz", "blanchedalmond")
);
stage.setScene(new Scene(tabPane));
stage.show();
}
private Tab createTab(String tabName, String webColor) {
final Label content = new Label("0");
content.setAlignment(Pos.CENTER);
content.setPrefSize(200, 100);
content.setStyle("-fx-font-size: 30px; -fx-background-color: " + webColor + ";");
final Tab tab = new Tab(tabName);
tab.setContent(content);
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem = new MenuItem("Count Click");
menuItem.setOnAction(new EventHandler<ActionEvent>(){
@Override public void handle(ActionEvent e){
content.setText(
"" + (Integer.parseInt(content.getText()) + 1)
);
}
});
contextMenu.getItems().add(menuItem);
tab.setContextMenu(contextMenu);
return tab;
}
public static void main(String[] args) { Application.launch(args); }
}
Alternately to using an anonymous inner class this way, you could create an EventHandler subclass with a constructor that includes the Tab for which the EventHandler is attached.
class TabContextMenuHandler implements EventHandler<ActionEvent> {
private final Tab tab;
TabContextMenuHandler(Tab tab) {
this.tab = tab;
}
@Override public void handle(ActionEvent event) {
tab.setText("Activated by User");
}
}
Upvotes: 4