JavaFX UI控件教程(二十三)之Menu
翻譯自??Menu
本章介紹如何創建菜單和菜單欄,添加菜單項,將菜單分組,創建子菜單以及設置上下文菜單。
您可以使用以下JavaFX API類在JavaFX應用程序中構建菜單。
-
菜單欄
-
菜單項
-
菜單
-
CheckMenuItem
-
RadioMenuItem
-
菜單
-
CustomMenuItem
-
SeparatorMenuItem
-
-
-
上下文菜單
圖22-1顯示了具有典型菜單欄的應用程序的屏幕截圖。
圖22-1使用菜單欄和三個菜單類別的應用程序
?
在JavaFX應用程序中構建菜單
菜單是可以根據用戶的請求顯示的可操作項目列表。當菜單可見時,用戶可以選擇一個菜單項。用戶單擊某個項目后,菜單將返回隱藏模式。通過使用菜單,您可以通過在菜單中放置并不總是需要顯示的功能來節省應用程序用戶界面(UI)中的空間。
菜單欄中的菜單通常按類別分組。編碼模式是聲明菜單欄,定義類別菜單,并使用菜單項填充類別菜單。在JavaFX應用程序中構建菜單時,請使用以下菜單項類:
-
MenuItem?- 創建一個可操作的選項
-
Menu?- 創建子菜單
-
RadioButtonItem?- 創建互斥選擇
-
CheckMenuItem?- 創建可在選定和未選定狀態之間切換的選項
要分隔一個類別中的菜單項,請使用SeparatorMenuItem該類。
按菜單欄中的類別組織的菜單通常位于窗口的頂部,剩下的場景用于關鍵的UI元素。如果出于某些原因,您無法為菜單欄分配UI的任何可視部分,則可以使用用戶打開的上下文菜單,只需單擊鼠標即可。
創建菜單欄
雖然菜單欄可以放在用戶界面的其他位置,但通常它位于UI的頂部,并且它包含一個或多個菜單。菜單欄會自動調整大小以適合應用程序窗口的寬度。默認情況下,添加到菜單欄的每個菜單都由帶有文本值的按鈕表示。
考慮一個呈現有關植物的參考信息的應用程序,例如它們的名稱,二項式名稱,圖片和簡要描述。您可以創建三個菜單類別:文件,編輯和視圖,并使用菜單項填充它們。例22-1顯示了添加了菜單欄的此類應用程序的源代碼。
示例22-1菜單示例應用程序
import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.effect.DropShadow; import javafx.scene.effect.Effect; import javafx.scene.effect.Glow; import javafx.scene.effect.SepiaTone; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage;public class MenuSample extends Application {final PageData[] pages = new PageData[] {new PageData("Apple","The apple is the pomaceous fruit of the apple tree, species Malus "+ "domestica in the rose family (Rosaceae). It is one of the most "+ "widely cultivated tree fruits, and the most widely known of "+ "the many members of genus Malus that are used by humans. "+ "The tree originated in Western Asia, where its wild ancestor, "+ "the Alma, is still found today.","Malus domestica"),new PageData("Hawthorn","The hawthorn is a large genus of shrubs and trees in the rose "+ "family, Rosaceae, native to temperate regions of the Northern "+ "Hemisphere in Europe, Asia and North America. "+ The name hawthorn was "+ "originally applied to the species native to northern Europe, "+ "especially the Common Hawthorn C. monogyna, and the unmodified "+ "name is often so used in Britain and Ireland.","Crataegus monogyna"),new PageData("Ivy","The ivy is a flowering plant in the grape family (Vitaceae) native to+ " eastern Asia in Japan, Korea, and northern and eastern China. "+ "It is a deciduous woody vine growing to 30 m tall or more given "+ "suitable support, attaching itself by means of numerous small "+ "branched tendrils tipped with sticky disks.","Parthenocissus tricuspidata"),new PageData("Quince","The quince is the sole member of the genus Cydonia and is native to "+ "warm-temperate southwest Asia in the Caucasus region. The "+ "immature fruit is green with dense grey-white pubescence, most "+ "of which rubs off before maturity in late autumn when the fruit "+ "changes color to yellow with hard, strongly perfumed flesh.","Cydonia oblonga")};final String[] viewOptions = new String[] {"Title", "Binomial name", "Picture", "Description"};final Entry<String, Effect>[] effects = new Entry[] {new SimpleEntry<String, Effect>("Sepia Tone", new SepiaTone()),new SimpleEntry<String, Effect>("Glow", new Glow()),new SimpleEntry<String, Effect>("Shadow", new DropShadow())};final ImageView pic = new ImageView();final Label name = new Label();final Label binName = new Label();final Label description = new Label();public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage stage) {stage.setTitle("Menu Sample");Scene scene = new Scene(new VBox(), 400, 350);scene.setFill(Color.OLDLACE);MenuBar menuBar = new MenuBar();// --- Menu FileMenu menuFile = new Menu("File");// --- Menu EditMenu menuEdit = new Menu("Edit");// --- Menu ViewMenu menuView = new Menu("View");menuBar.getMenus().addAll(menuFile, menuEdit, menuView);((VBox) scene.getRoot()).getChildren().addAll(menuBar);stage.setScene(scene);stage.show();}private class PageData {public String name;public String description;public String binNames;public Image image;public PageData(String name, String description, String binNames) {this.name = name;this.description = description;this.binNames = binNames;image = new Image(getClass().getResourceAsStream(name + ".jpg"));}} }與其他UI控件不同,Menu類的類和其他擴展MenuItem不會擴展Node類。它們無法直接添加到應用程序場景中,并且在通過該getMenus方法添加到菜單欄之前保持不可見。
圖22-2菜單欄已添加到應用程序中
您可以使用鍵盤的箭頭鍵瀏覽菜單。但是,當您選擇菜單時,不執行任何操作,因為尚未定義菜單的行為。
?
添加菜單項
通過添加以下項來設置“文件”菜單的功能:
-
隨機播放 - 加載有關植物的參考信息
-
清除 - 刪除參考信息并清除場景
-
分隔符 - 分離菜單項
-
退出 - 退出應用程序
例22-2中的粗線通過使用MenuItem類創建了一個Shuffle菜單,并將圖形組件添加到應用程序場景中。該MenuItem級能夠創建帶有文本和圖形的動作項。用戶單擊執行的操作由setOnAction方法定義,類似于Button類。
示例22-2使用Graphics添加Shuffle菜單項
import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.effect.DropShadow; import javafx.scene.effect.Effect; import javafx.scene.effect.Glow; import javafx.scene.effect.SepiaTone; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.TextAlignment; import javafx.stage.Stage;public class MenuSample extends Application {final PageData[] pages = new PageData[] {new PageData("Apple","The apple is the pomaceous fruit of the apple tree, species Malus "+"domestica in the rose family (Rosaceae). It is one of the most "+"widely cultivated tree fruits, and the most widely known of "+"the many members of genus Malus that are used by humans. "+"The tree originated in Western Asia, where its wild ancestor, "+"the Alma, is still found today.","Malus domestica"),new PageData("Hawthorn","The hawthorn is a large genus of shrubs and trees in the rose "+ "family, Rosaceae, native to temperate regions of the Northern "+ "Hemisphere in Europe, Asia and North America. "+ "The name hawthorn was "+ "originally applied to the species native to northern Europe, "+ "especially the Common Hawthorn C. monogyna, and the unmodified "+ "name is often so used in Britain and Ireland.","Crataegus monogyna"),new PageData("Ivy","The ivy is a flowering plant in the grape family (Vitaceae) native"+" to eastern Asia in Japan, Korea, and northern and eastern China."+" It is a deciduous woody vine growing to 30 m tall or more given "+"suitable support, attaching itself by means of numerous small "+"branched tendrils tipped with sticky disks.","Parthenocissus tricuspidata"),new PageData("Quince","The quince is the sole member of the genus Cydonia and is native"+" to warm-temperate southwest Asia in the Caucasus region. The "+"immature fruit is green with dense grey-white pubescence, most "+"of which rubs off before maturity in late autumn when the fruit "+"changes color to yellow with hard, strongly perfumed flesh.","Cydonia oblonga")};final String[] viewOptions = new String[] {"Title", "Binomial name", "Picture", "Description"};final Entry<String, Effect>[] effects = new Entry[] {new SimpleEntry<String, Effect>("Sepia Tone", new SepiaTone()),new SimpleEntry<String, Effect>("Glow", new Glow()),new SimpleEntry<String, Effect>("Shadow", new DropShadow())};final ImageView pic = new ImageView();final Label name = new Label();final Label binName = new Label();final Label description = new Label();private int currentIndex = -1;public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage stage) {stage.setTitle("Menu Sample");Scene scene = new Scene(new VBox(), 400, 350);scene.setFill(Color.OLDLACE);name.setFont(new Font("Verdana Bold", 22));binName.setFont(new Font("Arial Italic", 10));pic.setFitHeight(150);pic.setPreserveRatio(true);description.setWrapText(true);description.setTextAlignment(TextAlignment.JUSTIFY);shuffle();MenuBar menuBar = new MenuBar();final VBox vbox = new VBox();vbox.setAlignment(Pos.CENTER);vbox.setSpacing(10);vbox.setPadding(new Insets(0, 10, 0, 10));vbox.getChildren().addAll(name, binName, pic, description);// --- Menu FileMenu menuFile = new Menu("File");MenuItem add = new MenuItem("Shuffle",new ImageView(new Image("menusample/new.png")));add.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {shuffle();vbox.setVisible(true);}}); menuFile.getItems().addAll(add);// --- Menu EditMenu menuEdit = new Menu("Edit");// --- Menu ViewMenu menuView = new Menu("View");menuBar.getMenus().addAll(menuFile, menuEdit, menuView);((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);stage.setScene(scene);stage.show();}private void shuffle() {int i = currentIndex;while (i == currentIndex) {i = (int) (Math.random() * pages.length);}pic.setImage(pages[i].image);name.setText(pages[i].name);binName.setText("(" + pages[i].binNames + ")");description.setText(pages[i].description);currentIndex = i;}private class PageData {public String name;public String description;public String binNames;public Image image;public PageData(String name, String description, String binNames) {this.name = name;this.description = description;this.binNames = binNames;image = new Image(getClass().getResourceAsStream(name + ".jpg"));}} }當用戶選擇Shuffle菜單項時,shuffle調用的方法setOnAction通過計算相應數組中元素的索引來指定標題,二項式名稱,工廠圖片及其描述。
“清除”菜單項用于擦除應用程序場景。您可以通過使VBox具有GUI元素的容器不可見來實現此操作,如例22-3所示。
示例22-3使用加速器創建清除菜單項
MenuItem clear = new MenuItem("Clear"); clear.setAccelerator(KeyCombination.keyCombination("Ctrl+X")); clear.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {vbox.setVisible(false);} });在實施MenuItem類別可讓開發設置菜單加速器,執行相同的動作的菜單項的組合鍵。使用“清除”菜單,用戶可以從“文件”菜單類別中選擇操作,也可以同時按下“控制鍵”和“X”鍵。
Exit菜單關閉應用程序窗口。設置System.exit(0)為此菜單項的操作,如例22-4所示。
示例22-4創建退出菜單項
MenuItem exit = new MenuItem("Exit"); exit.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {System.exit(0);} });使用示例22-5中getItems顯示的方法將新創建的菜單項添加到“文件”菜單。您可以創建一個分隔符菜單項并將其添加到方法中,以便可視地分離“退出”菜單項。getItems
示例22-5添加菜單項
menuFile.getItems().addAll(add, clear, new SeparatorMenuItem(), exit);將示例22-2,示例22-3,示例22-4和示例22-5添加到Menu Sample應用程序,然后編譯并運行它。選擇Shuffle菜單項以加載有關不同植物的參考信息。然后清除場景(清除),并關閉應用程序(退出)。圖22-3顯示了Clear菜單項的選擇。
圖22-3包含三個菜單項的文件菜單
使用“視圖”菜單,您可以隱藏和顯示參考信息的元素。實現createMenuItem方法并在方法中調用它start以創建四個CheckMenuItem對象。然后將新創建的檢查菜單項添加到“視圖”菜單,以切換標題,二項式名稱,工廠圖片及其描述的可見性。例22-6顯示了實現這些任務的兩個代碼片段。
示例22-6應用CheckMenuItem類創建切換選項
// --- Creating four check menu items within the start method CheckMenuItem titleView = createMenuItem ("Title", name); CheckMenuItem binNameView = createMenuItem ("Binomial name", binName); CheckMenuItem picView = createMenuItem ("Picture", pic); CheckMenuItem descriptionView = createMenuItem ("Description", description); menuView.getItems().addAll(titleView, binNameView, picView, descriptionView);...// The createMenuItem method private static CheckMenuItem createMenuItem (String title, final Node node){CheckMenuItem cmi = new CheckMenuItem(title);cmi.setSelected(true);cmi.selectedProperty().addListener(new ChangeListener<Boolean>() {public void changed(ObservableValue ov,Boolean old_val, Boolean new_val) {node.setVisible(new_val);}});return cmi; }該CheckMenuItem班是的擴展MenuItem類。它可以在選定和取消選擇的狀態之間切換。選中后,檢查菜單項會顯示復選標記。
例22-6創建了四個CheckMenuItem對象并處理其selectedProperty屬性的更改。例如,當用戶取消選擇該項時picView,該setVisible方法接收該false值,該工廠的圖片變得不可見。將此代碼片段添加到應用程序,編譯并運行應用程序時,您可以嘗試選擇和取消選擇菜單項。圖22-4顯示了顯示工廠標題和圖片時的應用程序,但隱藏了其二項式名稱和描述。
圖22-4使用檢查菜單項
?
創建子菜單
對于“編輯”菜單,定義兩個菜單項:“圖片效果”和“無效果”。“圖片效果”菜單項被設計為具有三個項目的子菜單,用于設置三種可用視覺效果中的一種。“無效果”菜單項將刪除所選效果并恢復圖像的初始狀態。
使用RadioMenuItem該類創建子菜單的項目。將單選菜單按鈕添加到切換組以使選擇互斥。例22-7實現了這些任務。
示例22-7使用單選菜單項創建子菜單
//Picture Effect menu Menu menuEffect = new Menu("Picture Effect"); final ToggleGroup groupEffect = new ToggleGroup(); for (Entry<String, Effect> effect : effects) {RadioMenuItem itemEffect = new RadioMenuItem(effect.getKey());itemEffect.setUserData(effect.getValue());itemEffect.setToggleGroup(groupEffect);menuEffect.getItems().add(itemEffect); } //No Effects menu final MenuItem noEffects = new MenuItem("No Effects");noEffects.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {pic.setEffect(null);groupEffect.getSelectedToggle().setSelected(false);} });//Processing menu item selection groupEffect.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {public void changed(ObservableValue<? extends Toggle> ov,Toggle old_toggle, Toggle new_toggle) {if (groupEffect.getSelectedToggle() != null) {Effect effect = (Effect) groupEffect.getSelectedToggle().getUserData();pic.setEffect(effect);}}}); //Adding items to the Edit menu menuEdit.getItems().addAll(menuEffect, noEffects);該setUserData方法定義特定無線電菜單項的視覺效果。當選擇切換組中的一個項目時,相應的效果將應用于圖片。選擇“無效果”菜單項時,該setEffect方法指定該null值,并且不對圖片應用任何效果。
圖22-5捕獲用戶選擇Shadow菜單項的時刻。
圖22-5帶有三個單選菜單項的子菜單
當DropShadow效果被施加到圖像,它看起來如圖圖22-6。
圖22-6應用了DropShadow效果的Quince圖片
在“圖片效果”子菜單中未選擇任何效果時,可以使用類的setDisable方法MenuItem禁用“無效果”菜單。修改例22-7,如例22-8所示。
示例22-8禁用菜單項
Menu menuEffect = new Menu("Picture Effect"); final ToggleGroup groupEffect = new ToggleGroup(); for (Entry<String, Effect> effect : effects) {RadioMenuItem itemEffect = new RadioMenuItem(effect.getKey());itemEffect.setUserData(effect.getValue());itemEffect.setToggleGroup(groupEffect);menuEffect.getItems().add(itemEffect); } final MenuItem noEffects = new MenuItem("No Effects"); noEffects.setDisable(true); noEffects.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {pic.setEffect(null);groupEffect.getSelectedToggle().setSelected(false);noEffects.setDisable(true);} });groupEffect.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {public void changed(ObservableValue<? extends Toggle> ov,Toggle old_toggle, Toggle new_toggle) {if (groupEffect.getSelectedToggle() != null) {Effect effect = (Effect) groupEffect.getSelectedToggle().getUserData();pic.setEffect(effect);noEffects.setDisable(false);} else {noEffects.setDisable(true);}} }); menuEdit.getItems().addAll(menuEffect, noEffects);如果未RadioMenuItem選擇任何選項,則禁用“無效果”菜單項,如圖22-7所示。當用戶選擇其中一個視覺效果時,將啟用“無效果”菜單項。
圖22-7效果菜單項被禁用
?
添加上下文菜單
如果無法為所需功能分配用戶界面的任何空間,則可以使用上下文菜單。上下文菜單是一個彈出窗口,響應鼠標單擊而顯示。上下文菜單可以包含一個或多個菜單項。
在“菜單示例”應用程序中,為工廠的圖片設置上下文菜單,以便用戶可以復制圖像。
使用ContextMenu該類定義上下文菜單,如例22-9所示。
示例22-9定義上下文菜單
final ContextMenu cm = new ContextMenu(); MenuItem cmItem1 = new MenuItem("Copy Image"); cmItem1.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent e) {Clipboard clipboard = Clipboard.getSystemClipboard();ClipboardContent content = new ClipboardContent();content.putImage(pic.getImage());clipboard.setContent(content);} });cm.getItems().add(cmItem1); pic.addEventHandler(MouseEvent.MOUSE_CLICKED,new EventHandler<MouseEvent>() {@Override public void handle(MouseEvent e) {if (e.getButton() == MouseButton.SECONDARY) cm.show(pic, e.getScreenX(), e.getScreenY());} });當用戶右鍵單擊該ImageView對象時,將show調用該方法以使其顯示上下文菜單。
setOnAction為上下文菜單的“復制圖像”項定義的方法會創建一個Clipboard對象,并將圖像添加為其內容。圖22-8捕獲用戶選擇“復制圖像”上下文菜單項的時刻。
圖22-8使用上下文菜單
您可以嘗試復制圖像并將其粘貼到圖形編輯器中。
要進一步增強,可以向上下文菜單添加更多菜單項并指定不同的操作。您還可以使用CustomMenuItem該類創建自定義菜單。使用此類,您可以在菜單中嵌入任意節點,并指定例如按鈕或滑塊作為菜單項。
?
相關的API文檔?
-
Menu
-
MenuItem
-
RadioMenuItem
-
CheckMenuItem
-
ContextMenu
-
SeparatorMenuItem
-
CustomMenuItem
總結
以上是生活随笔為你收集整理的JavaFX UI控件教程(二十三)之Menu的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 亿道推出首款搭载英特尔 Meteor L
- 下一篇: java美元兑换,(Java实现) 美元