JavaFX菜單(Menu)

菜單是桌面應用程序選擇選項的標準方法。
菜單和菜單項可以與選擇選項快捷鍵組合,稱爲鍵盤快捷鍵。

創建菜單和菜單項

必須創建一個菜單欄javafx.scene.control.MenuBar對象來保存javafx.scene.control.Menu對象。

菜單對象可以包含Menujavafx.scene.control.MenuItem對象。菜單可以包含其他菜單作爲子菜單。MenuItemsMenu對象內的子選項。

以下代碼顯示如何創建菜單欄並添加菜單和菜單項。

Menu類是MenuItem的子類,它有一個getItems().add()方法,它能夠添加諸如其他MenuMenuItem實例的子元素。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.CheckMenuItem;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    BorderPane root = new BorderPane();
    Scene scene = new Scene(root, 300, 250, Color.WHITE);

    MenuBar menuBar = new MenuBar();
    menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
    root.setTop(menuBar);

    // File menu - new, save, exit
    Menu fileMenu = new Menu("File");
    MenuItem newMenuItem = new MenuItem("New");
    MenuItem saveMenuItem = new MenuItem("Save");
    MenuItem exitMenuItem = new MenuItem("Exit");
    exitMenuItem.setOnAction(actionEvent -> Platform.exit());

    fileMenu.getItems().addAll(newMenuItem, saveMenuItem,
        new SeparatorMenuItem(), exitMenuItem);

    Menu webMenu = new Menu("Web");
    CheckMenuItem htmlMenuItem = new CheckMenuItem("HTML");
    htmlMenuItem.setSelected(true);
    webMenu.getItems().add(htmlMenuItem);

    CheckMenuItem cssMenuItem = new CheckMenuItem("CSS");
    cssMenuItem.setSelected(true);
    webMenu.getItems().add(cssMenuItem);

    Menu sqlMenu = new Menu("SQL");
    ToggleGroup tGroup = new ToggleGroup();
    RadioMenuItem mysqlItem = new RadioMenuItem("MySQL");
    mysqlItem.setToggleGroup(tGroup);

    RadioMenuItem oracleItem = new RadioMenuItem("Oracle");
    oracleItem.setToggleGroup(tGroup);
    oracleItem.setSelected(true);

    sqlMenu.getItems().addAll(mysqlItem, oracleItem,
        new SeparatorMenuItem());

    Menu tutorialManeu = new Menu("Tutorial");
    tutorialManeu.getItems().addAll(
        new CheckMenuItem("Java"),
        new CheckMenuItem("JavaFX"),
        new CheckMenuItem("Swing"));

    sqlMenu.getItems().add(tutorialManeu);

    menuBar.getMenus().addAll(fileMenu, webMenu, sqlMenu);

    primaryStage.setScene(scene);
    primaryStage.show();
  }
  public static void main(String[] args) {
    launch(args);
  }
}

上面的代碼生成以下結果。
JavaFX菜單(Menu)

指定菜單項

要將選中的選項或單選按鈕添加到菜單,可以使用MenuItem類作爲菜單的子類。以下列表顯示了可用作菜單選項的MenuItem子類。

  • javafx.scene.control.CheckMenuItem
  • javafx.scene.control.RadioMenuItem
  • javafx.scene.control.CustomMenuItem
  • javafx.scene.control.SeparatorMenuItem
  • javafx.scene.control.Menu

CheckMenuItem菜單項類似於複選框控件,允許用戶選擇項。
RadioMenuItem菜單項類似於RadioButton控件,允許用戶從項目組中僅選擇一個項目。

要創建自定義菜單項,可以使用CustomMenuItem類。SeparatorMenuItemCustomMenuItem類型的派生類,並顯示用於分隔菜單項的視線。使用CustomMenuItemSlider添加到MenuItem上。可參考以下代碼實現 -

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.Slider;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

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

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Menus");
        Group root = new Group();
        Scene scene = new Scene(root, 300, 250, Color.WHITE);

        MenuBar menuBar = new MenuBar();

        Menu menu = new Menu("File");
        menu.getItems().add(new MenuItem("New"));
        menu.getItems().add(new MenuItem("Save"));
        menu.getItems().add(new SeparatorMenuItem());
        menu.getItems().add(new MenuItem("Exit"));

        CustomMenuItem customMenuItem = new CustomMenuItem(new Slider());
        customMenuItem.setHideOnClick(false);
        menu.getItems().add(customMenuItem);

        menuBar.getMenus().add(menu);

        menuBar.prefWidthProperty().bind(primaryStage.widthProperty());

        root.getChildren().add(menuBar); 
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

上面的代碼生成以下結果。
JavaFX菜單(Menu)

菜單事件處理程序

要向菜單項添加事件處理程序,可以使用setOnAction()方法,它接收一個類型爲EventHandler <ActionEvent>的功能接口,它是在選擇菜單項時調用的處理程序代碼。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    BorderPane root = new BorderPane();
    Scene scene = new Scene(root, 300, 250, Color.WHITE);

    MenuBar menuBar = new MenuBar();
    menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
    root.setTop(menuBar);

    Menu fileMenu = new Menu("File");
    MenuItem exitMenuItem = new MenuItem("Exit");
    fileMenu.getItems().add(exitMenuItem);
    exitMenuItem.setOnAction(actionEvent -> Platform.exit());

    menuBar.getMenus().addAll(fileMenu);

    primaryStage.setScene(scene);
    primaryStage.show();
  }
  public static void main(String[] args) {
    launch(args);
  }
}

上面的代碼生成以下結果。
JavaFX菜單(Menu)

關鍵助記符

標準菜單通常具有鍵盤助記符(類似於快捷鍵),以在不使用鼠標的情況下選擇菜單項。
用戶可以按Alt鍵和帶下劃線_的字母來激活菜單,然後使用箭頭鍵導航。要向菜單添加鍵助記符,使用String值調用構造函數,並在菜單或菜單項的文本中在所選字母前面放置一個下劃線字符。

然後將true傳遞給setMnemonicParsing(true)方法。

以下代碼創建一個使用字母「F」作爲助記符的文件菜單。

Menu fileMenu = new Menu("_File");
fileMenu.setMnemonicParsing(true);

完整的源代碼實現,如下所示 -

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    BorderPane root = new BorderPane();
    Scene scene = new Scene(root, 300, 250, Color.WHITE);

    MenuBar menuBar = new MenuBar();
    menuBar.prefWidthProperty().bind(primaryStage.widthProperty());
    root.setTop(menuBar);

    Menu fileMenu = new Menu("_File");
    fileMenu.setMnemonicParsing(true);
    MenuItem exitMenuItem = new MenuItem("Exit");
    fileMenu.getItems().add(exitMenuItem);
    exitMenuItem.setOnAction(actionEvent -> Platform.exit());

    menuBar.getMenus().addAll(fileMenu);

    primaryStage.setScene(scene);
    primaryStage.show();
  }
  public static void main(String[] args) {
    launch(args);
  }
}

上面的代碼生成以下結果(同時按住Ctrl + ALT + F)。
JavaFX菜單(Menu)

鍵組合

鍵組合是用於選擇菜單選項的鍵擊的組合。鍵組合稱爲鍵盤快捷鍵。

例如,在Windows平臺上,Ctrl + S的組合鍵可以保存文件。 在Mac OS平臺上,組合鍵爲Command + S.

CtrlCommandAltShiftMeta等鍵稱爲修飾鍵。

通常,修飾符與單個字母組合使用。要創建一個組合鍵,使用KeyCodeCombination對象,並傳入擊鍵和修飾符。

以下代碼創建(CtrlMeta)+ S的鍵代碼組合。

MenuItem saveItem = new MenuItem("_Save");
saveItem.setMnemonicParsing(true);
saveItem.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN));

代碼使用KeyCombination.SHORTCUT_DOWN值作爲鍵修飾符,而不是CONTROL_DOWNMETA_DOWNSHORTCUT_DOWN值將使應用程序能夠跨平臺使用。

CONTROL_DOWNMETA_DOWN值分別依賴於Windows和MacOS平臺,但是SHORTCUT_DOWN在所有平臺上都有效。

上下文菜單

上下文菜單是當用戶右鍵單擊鼠標按鈕時顯示的彈出菜單。

要創建上下文菜單,請使用ContextMenu類。ContextMenu菜單有一個getItems().add()方法來添加菜單項。

以下代碼顯示了使用菜單項(exitItem)實例化的上下文菜單:

ContextMenu  contextFileMenu = new ContextMenu(exitItem);

要響應鼠標右鍵單擊,請添加一個事件處理程序,以監聽右鍵單擊事件並調用上下文菜單的show()方法。

以下代碼設置了一個事件處理程序,以分別基於右鍵或左鍵單擊來顯示和隱藏上下文菜單。

hide()方法由主鼠標單擊(左鍵單擊)調用以刪除上下文菜單。

primaryStage.addEventHandler(MouseEvent.MOUSE_CLICKED,  (MouseEvent  me) ->  {
    if (me.getButton() == MouseButton.SECONDARY  || me.isControlDown())  {
        contextFileMenu.show(root, me.getScreenX(), me.getScreenY());
    }  else  {
        contextFileMenu.hide();
    }
});