Hướng dẫn sử dụng JavaFX ContextMenu
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- JavaFX ContextMenu

Khi bạn không thể cấp bất kỳ không gian của giao diện người dùng của bạn cho một chức năng cần thiết, bạn có thể sử dụng một trình đơn ngữ cảnh ( ContextMenu). Một trình đơn ngữ cảnh là một cửa sổ pop-up xuất hiện để đáp ứng với một cú nhấp chuột. Một menu ngữ cảnh có thể chứa một hoặc nhiều mục menu.
Chú ý rằng ContextMenu khá giống với một Menu, bạn có thể thêm các item kiểu MenuItem, CheckMenuItem, RadioMenuItemSeparatorMenuItem vào nó.

2- Ví dụ ContextMenu

Ví dụ đơn giản dưới đây minh họa một ContextMenu sẽ hiển thị khi người dùng nhấn phải chuột vào một đường tròn.
ContextMenuDemo.java
package org.o7planning.javafx.contextmenu;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class ContextMenuDemo extends Application {

   @Override
   public void start(Stage stage) {

       Label label = new Label();

       Circle circle = new Circle();
       circle.setRadius(80);
       circle.setFill(Color.AQUA);

       VBox root = new VBox();
       root.setPadding(new Insets(5));
       root.setSpacing(5);

       root.getChildren().addAll(label, circle);

 
       // Tạo đối tượng ContextMenu
       ContextMenu contextMenu = new ContextMenu();

       MenuItem item1 = new MenuItem("Menu Item 1");
       item1.setOnAction(new EventHandler<ActionEvent>() {

           @Override
           public void handle(ActionEvent event) {
               label.setText("Select Menu Item 1");
           }
       });
       MenuItem item2 = new MenuItem("Menu Item 2");
       item2.setOnAction(new EventHandler<ActionEvent>() {

           @Override
           public void handle(ActionEvent event) {
               label.setText("Select Menu Item 2");
           }
       });

 
       // Thêm các MenuItem vào MenuContext
       contextMenu.getItems().addAll(item1, item2);
 
       // Khi người dùng nhấn phải chuột vào hình tròn.
       circle.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {

           @Override
           public void handle(ContextMenuEvent event) {

               contextMenu.show(circle, event.getScreenX(), event.getScreenY());
           }
       });

       Scene scene = new Scene(root, 400, 200);

       stage.setTitle("JavaFX ContextMenu (o7planning.org)");
       stage.setScene(scene);
       stage.show();
   }

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

}

3- Phím tắt và các loại MenuItem

Cũng giống với Menu, bạn có thể thêm các item có kiểu MenuItem, CheckMenuItem, RadioMenuItem, SeparatorMenuItem vào ContextMenu. Bạn cũng có thể gắn các phím tắt (Accelerator) vào các item, người dùng có thể nhấn tổ hợp phím tắt thay thế cho việc click vào item đó.
ContextMenuDemo2.java
package org.o7planning.javafx.contextmenu;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class ContextMenuDemo2 extends Application {

    @Override
    public void start(Stage stage) {

        Circle circle = new Circle();
        circle.setRadius(80);
        circle.setFill(Color.AQUA);

        VBox root = new VBox();
        root.setPadding(new Insets(5));
        root.setSpacing(5);

        root.getChildren().addAll(circle);

 
        // Tạo đối tượng ContextMenu
        ContextMenu contextMenu = new ContextMenu();

        MenuItem menuItem = new MenuItem("Menu Item");

 
        // Sét phím tắt cho menuItem
        menuItem.setAccelerator(KeyCombination.keyCombination("Ctrl+O"));

        Menu parentMenu = new Menu("Parent");
        MenuItem childMenuItem1 = new MenuItem("Child 1");
        MenuItem childMenuItem2 = new MenuItem("Child 2");
        parentMenu.getItems().addAll(childMenuItem1, childMenuItem2);

        CheckMenuItem checkMenuItem = new CheckMenuItem("Check Menu Item");
        checkMenuItem.setSelected(true);

        SeparatorMenuItem separatorMenuItem = new SeparatorMenuItem();

        RadioMenuItem radioMenuItem1 = new RadioMenuItem("Radio - Option 1");
        RadioMenuItem radioMenuItem2 = new RadioMenuItem("Radio - Option 2");
        ToggleGroup group = new ToggleGroup();

        radioMenuItem1.setToggleGroup(group);
        radioMenuItem2.setToggleGroup(group);

 
        // Thêm các MenuItem vào MenuContext
        contextMenu.getItems().addAll(menuItem, parentMenu, checkMenuItem, //
                separatorMenuItem, radioMenuItem1, radioMenuItem2);
 
        // Khi người dùng nhấn phải chuột vào hình tròn.
        circle.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {

            @Override
            public void handle(ContextMenuEvent event) {

                contextMenu.show(circle, event.getScreenX(), event.getScreenY());
            }
        });

        Scene scene = new Scene(root, 400, 200);

        stage.setTitle("JavaFX ContextMenu (o7planning.org)");
        stage.setScene(scene);
        stage.show();
    }

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

}

4- ContextMenu và sự kiện

Có một vài sự kiện của ContextMenu, nó có thể có ích cho bạn chẳng hạn như onShowing là sự kiện phát ra ngay trước khi contextMenu đang bắt đầu hiển thị. Bạn có thể lợi dụng sự kiện này để làm một việc gì đó, chẳng hạn thêm các MenuItem vào ContextMenu.
// Được gọi ngay trước khi ContextMenu bắt đầu hiển thị
public final void setOnShowing(EventHandler<WindowEvent> value)

// Được gọi ngay sau khi ContextMenu hiển thị
public final void setOnShown(EventHandler<WindowEvent> value)

// Được gọi ngay trước khi ContextMenu bắt đầu ẩn
public final void setOnHiding(EventHandler<WindowEvent> value)

// Được gọi ngay sau khi ContextMenu ẩn
public final void setOnHidden(EventHandler<WindowEvent> value)

// Được gọi khi có một yêu cầu ẩn contextMenu từ bên ngoài.
public final void setOnCloseRequest(EventHandler<WindowEvent> value)
ContextMenuEventDemo.java
package org.o7planning.javafx.contextmenu;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class ContextMenuEventDemo extends Application {

   private int index = 1;

   @Override
   public void start(Stage stage) {

       TextArea textArea = new TextArea();
       textArea.setMinHeight(100);

       Circle circle = new Circle();
       circle.setRadius(80);
       circle.setFill(Color.GRAY);

       VBox root = new VBox();
       root.setPadding(new Insets(5));
       root.setSpacing(5);

       root.getChildren().addAll(textArea, circle);
 
       // Tạo đối tượng ContextMenu
       ContextMenu contextMenu = new ContextMenu();
       MenuItem menuItem = new MenuItem("Menu Item");
       contextMenu.getItems().add(menuItem);

 
       // Khi người dùng nhấn phải chuột vào hình tròn.
       circle.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {

           @Override
           public void handle(ContextMenuEvent event) {

               contextMenu.show(circle, event.getScreenX(), event.getScreenY());
           }
       });
 
       // Được gọi khi ContextMenu đang bắt đầu hiển thị.
       // Thêm các MenuItem vào
       contextMenu.setOnShowing(new EventHandler<WindowEvent>() {

           @Override
           public void handle(WindowEvent event) {
               textArea.appendText("On Showing..\n");

               MenuItem menuItem = new MenuItem("New Menu Item " + index++);
               contextMenu.getItems().add(menuItem);
           }
       });
 
       // Được gọi ngay sau khi ContextMenu hiển thị
       contextMenu.setOnShown(new EventHandler<WindowEvent>() {

           @Override
           public void handle(WindowEvent event) {
               textArea.appendText("On Show..\n");
           }
       });
   
       // Được gọi ngay trước khi ContextMenu chuẩn bị ẩn
       contextMenu.setOnHiding(new EventHandler<WindowEvent>() {

           @Override
           public void handle(WindowEvent event) {
               textArea.appendText("On Hiding..\n");
           }
       });
 
       // Được gọi ngay sau khi ContextMenu bị ẩn
       contextMenu.setOnHidden(new EventHandler<WindowEvent>() {

           @Override
           public void handle(WindowEvent event) {
               textArea.appendText("On Hidden..\n");
           }
       });

       Scene scene = new Scene(root, 400, 250);

       stage.setTitle("JavaFX ContextMenu (o7planning.org)");
       stage.setScene(scene);
       stage.show();
   }

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

}