JavaFX UI控件教程(二十三)之Menu
翻譯自??Menu
本章介紹如何創(chuàng)建菜單和菜單欄,添加菜單項(xiàng),將菜單分組,創(chuàng)建子菜單以及設(shè)置上下文菜單。
您可以使用以下JavaFX API類在JavaFX應(yīng)用程序中構(gòu)建菜單。
-
菜單欄
-
菜單項(xiàng)
-
菜單
-
CheckMenuItem
-
RadioMenuItem
-
菜單
-
CustomMenuItem
-
SeparatorMenuItem
-
-
-
上下文菜單
圖22-1顯示了具有典型菜單欄的應(yīng)用程序的屏幕截圖。
圖22-1使用菜單欄和三個(gè)菜單類別的應(yīng)用程序
?
在JavaFX應(yīng)用程序中構(gòu)建菜單
菜單是可以根據(jù)用戶的請(qǐng)求顯示的可操作項(xiàng)目列表。當(dāng)菜單可見(jiàn)時(shí),用戶可以選擇一個(gè)菜單項(xiàng)。用戶單擊某個(gè)項(xiàng)目后,菜單將返回隱藏模式。通過(guò)使用菜單,您可以通過(guò)在菜單中放置并不總是需要顯示的功能來(lái)節(jié)省應(yīng)用程序用戶界面(UI)中的空間。
菜單欄中的菜單通常按類別分組。編碼模式是聲明菜單欄,定義類別菜單,并使用菜單項(xiàng)填充類別菜單。在JavaFX應(yīng)用程序中構(gòu)建菜單時(shí),請(qǐng)使用以下菜單項(xiàng)類:
-
MenuItem?- 創(chuàng)建一個(gè)可操作的選項(xiàng)
-
Menu?- 創(chuàng)建子菜單
-
RadioButtonItem?- 創(chuàng)建互斥選擇
-
CheckMenuItem?- 創(chuàng)建可在選定和未選定狀態(tài)之間切換的選項(xiàng)
要分隔一個(gè)類別中的菜單項(xiàng),請(qǐng)使用SeparatorMenuItem該類。
按菜單欄中的類別組織的菜單通常位于窗口的頂部,剩下的場(chǎng)景用于關(guān)鍵的UI元素。如果出于某些原因,您無(wú)法為菜單欄分配UI的任何可視部分,則可以使用用戶打開(kāi)的上下文菜單,只需單擊鼠標(biāo)即可。
創(chuàng)建菜單欄
雖然菜單欄可以放在用戶界面的其他位置,但通常它位于UI的頂部,并且它包含一個(gè)或多個(gè)菜單。菜單欄會(huì)自動(dòng)調(diào)整大小以適合應(yīng)用程序窗口的寬度。默認(rèn)情況下,添加到菜單欄的每個(gè)菜單都由帶有文本值的按鈕表示。
考慮一個(gè)呈現(xiàn)有關(guān)植物的參考信息的應(yīng)用程序,例如它們的名稱,二項(xiàng)式名稱,圖片和簡(jiǎn)要描述。您可以創(chuàng)建三個(gè)菜單類別:文件,編輯和視圖,并使用菜單項(xiàng)填充它們。例22-1顯示了添加了菜單欄的此類應(yīng)用程序的源代碼。
示例22-1菜單示例應(yīng)用程序
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類的類和其他擴(kuò)展MenuItem不會(huì)擴(kuò)展Node類。它們無(wú)法直接添加到應(yīng)用程序場(chǎng)景中,并且在通過(guò)該getMenus方法添加到菜單欄之前保持不可見(jiàn)。
圖22-2菜單欄已添加到應(yīng)用程序中
您可以使用鍵盤(pán)的箭頭鍵瀏覽菜單。但是,當(dāng)您選擇菜單時(shí),不執(zhí)行任何操作,因?yàn)樯形炊x菜單的行為。
?
添加菜單項(xiàng)
通過(guò)添加以下項(xiàng)來(lái)設(shè)置“文件”菜單的功能:
-
隨機(jī)播放 - 加載有關(guān)植物的參考信息
-
清除 - 刪除參考信息并清除場(chǎng)景
-
分隔符 - 分離菜單項(xiàng)
-
退出 - 退出應(yīng)用程序
例22-2中的粗線通過(guò)使用MenuItem類創(chuàng)建了一個(gè)Shuffle菜單,并將圖形組件添加到應(yīng)用程序場(chǎng)景中。該MenuItem級(jí)能夠創(chuàng)建帶有文本和圖形的動(dòng)作項(xiàng)。用戶單擊執(zhí)行的操作由setOnAction方法定義,類似于Button類。
示例22-2使用Graphics添加Shuffle菜單項(xiàng)
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"));}} }當(dāng)用戶選擇Shuffle菜單項(xiàng)時(shí),shuffle調(diào)用的方法setOnAction通過(guò)計(jì)算相應(yīng)數(shù)組中元素的索引來(lái)指定標(biāo)題,二項(xiàng)式名稱,工廠圖片及其描述。
“清除”菜單項(xiàng)用于擦除應(yīng)用程序場(chǎng)景。您可以通過(guò)使VBox具有GUI元素的容器不可見(jiàn)來(lái)實(shí)現(xiàn)此操作,如例22-3所示。
示例22-3使用加速器創(chuàng)建清除菜單項(xiàng)
MenuItem clear = new MenuItem("Clear"); clear.setAccelerator(KeyCombination.keyCombination("Ctrl+X")); clear.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {vbox.setVisible(false);} });在實(shí)施MenuItem類別可讓開(kāi)發(fā)設(shè)置菜單加速器,執(zhí)行相同的動(dòng)作的菜單項(xiàng)的組合鍵。使用“清除”菜單,用戶可以從“文件”菜單類別中選擇操作,也可以同時(shí)按下“控制鍵”和“X”鍵。
Exit菜單關(guān)閉應(yīng)用程序窗口。設(shè)置System.exit(0)為此菜單項(xiàng)的操作,如例22-4所示。
示例22-4創(chuàng)建退出菜單項(xiàng)
MenuItem exit = new MenuItem("Exit"); exit.setOnAction(new EventHandler<ActionEvent>() {public void handle(ActionEvent t) {System.exit(0);} });使用示例22-5中g(shù)etItems顯示的方法將新創(chuàng)建的菜單項(xiàng)添加到“文件”菜單。您可以創(chuàng)建一個(gè)分隔符菜單項(xiàng)并將其添加到方法中,以便可視地分離“退出”菜單項(xiàng)。getItems
示例22-5添加菜單項(xiàng)
menuFile.getItems().addAll(add, clear, new SeparatorMenuItem(), exit);將示例22-2,示例22-3,示例22-4和示例22-5添加到Menu Sample應(yīng)用程序,然后編譯并運(yùn)行它。選擇Shuffle菜單項(xiàng)以加載有關(guān)不同植物的參考信息。然后清除場(chǎng)景(清除),并關(guān)閉應(yīng)用程序(退出)。圖22-3顯示了Clear菜單項(xiàng)的選擇。
圖22-3包含三個(gè)菜單項(xiàng)的文件菜單
使用“視圖”菜單,您可以隱藏和顯示參考信息的元素。實(shí)現(xiàn)createMenuItem方法并在方法中調(diào)用它start以創(chuàng)建四個(gè)CheckMenuItem對(duì)象。然后將新創(chuàng)建的檢查菜單項(xiàng)添加到“視圖”菜單,以切換標(biāo)題,二項(xiàng)式名稱,工廠圖片及其描述的可見(jiàn)性。例22-6顯示了實(shí)現(xiàn)這些任務(wù)的兩個(gè)代碼片段。
示例22-6應(yīng)用CheckMenuItem類創(chuàng)建切換選項(xiàng)
// --- 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班是的擴(kuò)展MenuItem類。它可以在選定和取消選擇的狀態(tài)之間切換。選中后,檢查菜單項(xiàng)會(huì)顯示復(fù)選標(biāo)記。
例22-6創(chuàng)建了四個(gè)CheckMenuItem對(duì)象并處理其selectedProperty屬性的更改。例如,當(dāng)用戶取消選擇該項(xiàng)時(shí)picView,該setVisible方法接收該false值,該工廠的圖片變得不可見(jiàn)。將此代碼片段添加到應(yīng)用程序,編譯并運(yùn)行應(yīng)用程序時(shí),您可以嘗試選擇和取消選擇菜單項(xiàng)。圖22-4顯示了顯示工廠標(biāo)題和圖片時(shí)的應(yīng)用程序,但隱藏了其二項(xiàng)式名稱和描述。
圖22-4使用檢查菜單項(xiàng)
?
創(chuàng)建子菜單
對(duì)于“編輯”菜單,定義兩個(gè)菜單項(xiàng):“圖片效果”和“無(wú)效果”。“圖片效果”菜單項(xiàng)被設(shè)計(jì)為具有三個(gè)項(xiàng)目的子菜單,用于設(shè)置三種可用視覺(jué)效果中的一種。“無(wú)效果”菜單項(xiàng)將刪除所選效果并恢復(fù)圖像的初始狀態(tài)。
使用RadioMenuItem該類創(chuàng)建子菜單的項(xiàng)目。將單選菜單按鈕添加到切換組以使選擇互斥。例22-7實(shí)現(xiàn)了這些任務(wù)。
示例22-7使用單選菜單項(xiàng)創(chuàng)建子菜單
//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方法定義特定無(wú)線電菜單項(xiàng)的視覺(jué)效果。當(dāng)選擇切換組中的一個(gè)項(xiàng)目時(shí),相應(yīng)的效果將應(yīng)用于圖片。選擇“無(wú)效果”菜單項(xiàng)時(shí),該setEffect方法指定該null值,并且不對(duì)圖片應(yīng)用任何效果。
圖22-5捕獲用戶選擇Shadow菜單項(xiàng)的時(shí)刻。
圖22-5帶有三個(gè)單選菜單項(xiàng)的子菜單
當(dāng)DropShadow效果被施加到圖像,它看起來(lái)如圖圖22-6。
圖22-6應(yīng)用了DropShadow效果的Quince圖片
在“圖片效果”子菜單中未選擇任何效果時(shí),可以使用類的setDisable方法MenuItem禁用“無(wú)效果”菜單。修改例22-7,如例22-8所示。
示例22-8禁用菜單項(xiàng)
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選擇任何選項(xiàng),則禁用“無(wú)效果”菜單項(xiàng),如圖22-7所示。當(dāng)用戶選擇其中一個(gè)視覺(jué)效果時(shí),將啟用“無(wú)效果”菜單項(xiàng)。
圖22-7效果菜單項(xiàng)被禁用
?
添加上下文菜單
如果無(wú)法為所需功能分配用戶界面的任何空間,則可以使用上下文菜單。上下文菜單是一個(gè)彈出窗口,響應(yīng)鼠標(biāo)單擊而顯示。上下文菜單可以包含一個(gè)或多個(gè)菜單項(xiàng)。
在“菜單示例”應(yīng)用程序中,為工廠的圖片設(shè)置上下文菜單,以便用戶可以復(fù)制圖像。
使用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());} });當(dāng)用戶右鍵單擊該ImageView對(duì)象時(shí),將show調(diào)用該方法以使其顯示上下文菜單。
setOnAction為上下文菜單的“復(fù)制圖像”項(xiàng)定義的方法會(huì)創(chuàng)建一個(gè)Clipboard對(duì)象,并將圖像添加為其內(nèi)容。圖22-8捕獲用戶選擇“復(fù)制圖像”上下文菜單項(xiàng)的時(shí)刻。
圖22-8使用上下文菜單
您可以嘗試復(fù)制圖像并將其粘貼到圖形編輯器中。
要進(jìn)一步增強(qiáng),可以向上下文菜單添加更多菜單項(xiàng)并指定不同的操作。您還可以使用CustomMenuItem該類創(chuàng)建自定義菜單。使用此類,您可以在菜單中嵌入任意節(jié)點(diǎn),并指定例如按鈕或滑塊作為菜單項(xiàng)。
?
相關(guān)的API文檔?
-
Menu
-
MenuItem
-
RadioMenuItem
-
CheckMenuItem
-
ContextMenu
-
SeparatorMenuItem
-
CustomMenuItem
總結(jié)
以上是生活随笔為你收集整理的JavaFX UI控件教程(二十三)之Menu的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 亿道推出首款搭载英特尔 Meteor L
- 下一篇: JavaFX UI控件教程(二十四)之P