Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX ContextMenu how do I get the clicked Object?

I am learning javafx.scene.control.ContextMenu, and right now I am facing a problem:

how do I get the clicked Object from EventHandler? both event.source() and event.target() return the MenuItem.

let me explain with an example: what should I write inside the function handle?

    TextField text = new TextField();
    Label label1 = new Label("hello");
    Label label2 = new Label("world");
    Label label3 = new Label("java");

    ContextMenu menu = new ContextMenu();
    MenuItem item = new MenuItem("copy to text field");
    menu.getItems().add(item);
    item.setOnAction(new EventHandler(){
        public void handle(Event event) {
            //I want to copy the text of the Label I clicked to TextField
            event.consume();
        }
    });

    label1.setContextMenu(menu);
    label2.setContextMenu(menu);
    label3.setContextMenu(menu);

EDIT: I was hoping there was some simple solution (one liner), but if there isn't then there are lot's of complex way to do it.

like image 621
hanbin615 Avatar asked Mar 19 '15 15:03

hanbin615


2 Answers

You could create your own instance of ContextMenu and add the action parent to it for further reference:

public class Main extends Application {

    TextField text = new TextField();

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {


        Label label1 = new Label("hello");
        Label label2 = new Label("world");
        Label label3 = new Label("java");

        label1.setContextMenu(new MyContextMenu(label1));
        label2.setContextMenu(new MyContextMenu(label2));
        label3.setContextMenu(new MyContextMenu(label3));

        HBox root = new HBox();

        root.getChildren().addAll(text, label1, label2, label3);

        Scene scene = new Scene(root, 300, 100);

        primaryStage.setScene(scene);
        primaryStage.show();

    }

    private class MyContextMenu extends ContextMenu {

        public MyContextMenu(Label label) {

            MenuItem item = new MenuItem("copy to text field");
            item.setOnAction(event -> {

                // I want to copy the text of the Label I clicked to TextField
                text.setText(label.getText());

                event.consume();
            });

            getItems().add(item);

        }

    }
}
like image 89
Roland Avatar answered Nov 08 '22 13:11

Roland


I think the easiest way is to save the Node as UserData of context menu.

EventHandler<? super ContextMenuEvent> eventHandle = e->menu.setUseData(e.getSource());
label1.setOnContextMenuRequested(eventHandle );
label2.setOnContextMenuRequested(eventHandle );
label3.setOnContextMenuRequested(eventHandle );

and in action:

EventHandler<ActionEvent> menuItemEvent = e->{
    Node node = (Node) ((MenuItem)e.getSource()).getParentPopup().getUserData();
   ...
};
like image 41
Oleksandr Potomkin Avatar answered Nov 08 '22 12:11

Oleksandr Potomkin