使用RadioMenuItem来创建子菜单的菜单项。将RadioMenuItem类型菜单项添加到ToggleGroup(互斥切换组)类型对象中,使各个RadioMenuItem类型菜单项的选中是相互排斥的效果
本例子实现:
通过setUserData()为每个RadioMenuItem定义了一个视觉特效。当ToggleGroup中的菜单项被选中时,对应的特效就会被应用在图片上。当NoEffects菜单项被选中时,setEffect()方法被赋值为null,没有特效应用在图片上
import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; 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.stage.Stage; import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; public class MenuSample extends Application { final PageData[] pages = new PageData[]{ new PageData("标题一", "描述一", "名称一"), new PageData("标题二", "描述二", "名称二"), new PageData("标题三", "描述三", "名称三"), new PageData("标题", "描述", "名称") }; final String[] viewOptions = new String[]{ "标题", "二项式", "图片", "描述" }; final Entry<String, Effect>[] effects = new Entry[]{//Entry类型数组对象的初始化 new SimpleEntry<>("褐色特效", new SepiaTone()),//创建一个深褐色特效 用SimpleEntry类型对象保存,key是String 而value 是特效对象 new SimpleEntry<>("发光特效", new Glow()),//创建一个发光特效,用SimpleEntry类型对象保存,key是String 而value 是特效对象 new SimpleEntry<>("阴影特效", new DropShadow())//创建一个阴影特效,用SimpleEntry类型对象保存,key是String 而value 是特效对象 }; 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); } @Override public void start(Stage stage) { stage.setTitle("Menu例子"); Scene scene = new Scene(new VBox(), 400, 350);//创建一个场景对象,并将场景上挂载一个垂直盒子Vbox布局对象 final VBox vbox = new VBox();//创建一个垂直布局对象 vbox.setAlignment(Pos.CENTER);//设置vbox对象对齐方式 vbox.setSpacing(10);//设置vbox对象布局的元素之间的空间距离 vbox.setPadding(new Insets(0, 10, 0, 10));//设置Vbox对象内边距 vbox.getChildren().addAll(name, binName, pic, description);//vbox布局器中要添加的被布局元素对象(用vbox对象布局相关Node类型Label标签型对象和ImageView类型对象) shuffle();//清晰复原程序 MenuBar menuBar = new MenuBar();//创建一个MenuBar类型对象 // --- Menu File Menu menuFile = new Menu("Menu选择图片"); // --- Menu Edit Menu menuEdit = new Menu("Menu图片编辑"); // --- Menu View Menu menuView = new Menu("Menu菜单三"); //将上文创建的三个Menu对象添加(镶嵌)到MenuBar对象上去 menuBar.getMenus().addAll(menuFile, menuEdit, menuView);//Menu类型对象都是要镶嵌在MenuBar对象上的 Menu menuEffect = new Menu("图片特效");//创建一个菜单(后续作为子菜单) final ToggleGroup groupEffect = new ToggleGroup();//创建一个互斥切换组对象 for (Entry<String, Effect> effect : effects) {//遍历保存了图形特效的List<SimpleEntry>类型对象 RadioMenuItem itemEffect = new RadioMenuItem(effect.getKey());//创建一个RadioMenuItem类型菜单选项对象 itemEffect.setUserData(effect.getValue());//将从SimpleEntry类型对象中获取的vlaue值(Effect类型图像特效对象)作为用户选择数据项内容设置给RadioMenuItem类型对象的用户选择数据内容 itemEffect.setToggleGroup(groupEffect);//将RadioMenuItem类型对象添加到一个互斥组对象中去 menuEffect.getItems().add(itemEffect);//将RadioMenuItem类型对象作为选项挂载到前文定义的 图片特效子菜单中 } //No Effects菜单 final MenuItem noEffects = new MenuItem("无特效");//创建一个普通菜单选项MenuItem类型对象 noEffects.setOnAction((ActionEvent t) -> {//给上文定义的菜单选项对象添加交互事件处理回调函数 pic.setEffect(null);//将ImageView类型对象pic的特效设置为null groupEffect.getSelectedToggle().setSelected(false);//将互斥组ToggleGroup类型对象groupEffect的被选中项的对象对应的选中状态设置为false未选状态 }); //处理菜单项的选中事件 groupEffect.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {//ToggleGroup类型对象的互斥选项,选项选中改变交互事件处理回调函数的编写 public void changed(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) { if (groupEffect.getSelectedToggle() != null) { Effect effect = (Effect) groupEffect.getSelectedToggle().getUserData();//获取切换组对象ToggleGroup 中选中的互斥选项对象对应的用户选中数据内容,本例中将选中数据内容转换成Effect类型图像特效对象 pic.setEffect(effect);//给ImageView类型对象pic添加图形效果 } } }); //ToggleGroup类型对象的互斥选项,选项选中改变交互事件处理回调函数的编写 groupEffect.selectedToggleProperty().addListener( (ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) -> { if (groupEffect.getSelectedToggle() != null) { //获取切换组对象ToggleGroup类型groupEffect对象 中选中的互斥选项对象对应的用户选中数据内容,本例中将选中数据内容转换成Effect类型图像特效对象 Effect effect = (Effect) groupEffect.getSelectedToggle().getUserData(); pic.setEffect(effect);//给ImageView类型对象pic添加图形效果对象effect } }); //向Edit菜单添加菜单项 menuEdit.getItems().addAll(menuEffect, noEffects);//向图像编辑主菜单添加挂载对应的子菜单和菜单选项 ((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);//scene对象的根节点元素上添加上文定义的menuBar对象和vbox对象,从场景对象scene对象上获取Vbox类型布局对象,并将前文定义的MenuBar类型对象添加到Vbox布局对象上去 stage.setScene(scene);//舞台上添加场景 stage.show();//舞台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);//label添加文字 binName.setText("(" + pages[i].binNames + ")");//label添加文字 description.setText(pages[i].description);//label对象添加文字 currentIndex = i; } private class PageData {//自定义的类似于pojo类型 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("archimedes.jpg"));//创建并加载一个图片对象 } } }
————————————
适当的时机禁用与启用 无特效选项
import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; 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.stage.Stage; import java.util.AbstractMap.SimpleEntry; import java.util.Map.Entry; public class MenuSample extends Application { final PageData[] pages = new PageData[]{ new PageData("标题一", "描述一", "名称一"), new PageData("标题二", "描述二", "名称二"), new PageData("标题三", "描述三", "名称三"), new PageData("标题", "描述", "名称") }; final String[] viewOptions = new String[]{ "标题", "二项式", "图片", "描述" }; final Entry<String, Effect>[] effects = new Entry[]{//Entry类型数组对象的初始化 new SimpleEntry<>("褐色特效", new SepiaTone()),//创建一个深褐色特效 用SimpleEntry类型对象保存,key是String 而value 是特效对象 new SimpleEntry<>("发光特效", new Glow()),//创建一个发光特效,用SimpleEntry类型对象保存,key是String 而value 是特效对象 new SimpleEntry<>("阴影特效", new DropShadow())//创建一个阴影特效,用SimpleEntry类型对象保存,key是String 而value 是特效对象 }; 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); } @Override public void start(Stage stage) { stage.setTitle("Menu例子"); Image image = new Image("https://www.dllg56.com/qt/img/logo-sing.png"); stage.getIcons().add(image); Scene scene = new Scene(new VBox(), 400, 350);//创建一个场景对象,并将场景上挂载一个垂直盒子Vbox布局对象 final VBox vbox = new VBox();//创建一个垂直布局对象 vbox.setAlignment(Pos.CENTER);//设置vbox对象对齐方式 vbox.setSpacing(10);//设置vbox对象布局的元素之间的空间距离 vbox.setPadding(new Insets(0, 10, 0, 10));//设置Vbox对象内边距 vbox.getChildren().addAll(name, binName, pic, description);//vbox布局器中要添加的被布局元素对象(用vbox对象布局相关Node类型Label标签型对象和ImageView类型对象) shuffle();//清晰复原程序 MenuBar menuBar = new MenuBar();//创建一个MenuBar类型对象 // --- Menu File Menu menuFile = new Menu("Menu选择图片"); // --- Menu Edit Menu menuEdit = new Menu("Menu图片编辑"); // --- Menu View Menu menuView = new Menu("Menu菜单三"); //将上文创建的三个Menu对象添加(镶嵌)到MenuBar对象上去 menuBar.getMenus().addAll(menuFile, menuEdit, menuView);//Menu类型对象都是要镶嵌在MenuBar对象上的 Menu menuEffect = new Menu("图片特效");//创建一个菜单(后续作为子菜单) final ToggleGroup groupEffect = new ToggleGroup();//创建一个互斥切换组对象 for (Entry<String, Effect> effect : effects) {//遍历保存了图形特效的List<SimpleEntry>类型对象 RadioMenuItem itemEffect = new RadioMenuItem(effect.getKey());//创建一个RadioMenuItem类型菜单选项对象 itemEffect.setUserData(effect.getValue());//将从SimpleEntry类型对象中获取的vlaue值(Effect类型图像特效对象)作为用户选择数据项内容设置给RadioMenuItem类型对象的用户选择数据内容 itemEffect.setToggleGroup(groupEffect);//将RadioMenuItem类型对象添加到一个互斥组对象中去 menuEffect.getItems().add(itemEffect);//将RadioMenuItem类型对象作为选下挂载到前文定义的 图片特效子菜单中 } //No Effects菜单 final MenuItem noEffects = new MenuItem("无特效");//创建一个普通菜单选项MenuItem类型对象 noEffects.setDisable(true);// 初始化无特效菜单选项是被禁用的 noEffects.setOnAction((ActionEvent t) -> {//给上文定义的菜单选项对象添加交互事件处理回调函数 pic.setEffect(null);//将ImageView类型对象pic的特效设置为null groupEffect.getSelectedToggle().setSelected(false);//将互斥组ToggleGroup类型对象groupEffect的被选中项的对象对应的选中状态设置为false未选状态 noEffects.setDisable(true);//引用无特效选项 }); //处理菜单项的选中事件 groupEffect.selectedToggleProperty().addListener(new ChangeListener<Toggle>() {//ToggleGroup类型对象的互斥选项,选项选中改变交互事件处理回调函数的编写 public void changed(ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) { if (groupEffect.getSelectedToggle() != null) { Effect effect = (Effect) groupEffect.getSelectedToggle().getUserData();//获取切换组对象ToggleGroup 中选中的互斥选项对象对应的用户选中数据内容,本例中将选中数据内容转换成Effect类型图像特效对象 pic.setEffect(effect);//给ImageView类型对象pic添加图形效果 } } }); //ToggleGroup类型对象的互斥选项,选项选中改变交互事件处理回调函数的编写 groupEffect.selectedToggleProperty().addListener( (ObservableValue<? extends Toggle> ov, Toggle old_toggle, Toggle new_toggle) -> { if (groupEffect.getSelectedToggle() != null) { //获取切换组对象ToggleGroup类型groupEffect对象 中选中的互斥选项对象对应的用户选中数据内容,本例中将选中数据内容转换成Effect类型图像特效对象 Effect effect = (Effect) groupEffect.getSelectedToggle().getUserData(); pic.setEffect(effect);//给ImageView类型对象pic添加图形效果对象effect noEffects.setDisable(false);//启用无特效选项 }else { noEffects.setDisable(true);//禁用无特效选项 } }); //向Edit菜单添加菜单项 menuEdit.getItems().addAll(menuEffect, noEffects);//向图像编辑主菜单添加挂载对应的子菜单和菜单选项 ((VBox) scene.getRoot()).getChildren().addAll(menuBar, vbox);//scene对象的根节点元素上添加上文定义的menuBar对象和vbox对象,从场景对象scene对象上获取Vbox类型布局对象,并将前文定义的MenuBar类型对象添加到Vbox布局对象上去 stage.setScene(scene);//舞台上添加场景 stage.show();//舞台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);//label添加文字 binName.setText("(" + pages[i].binNames + ")");//label添加文字 description.setText(pages[i].description);//label对象添加文字 currentIndex = i; } private class PageData {//自定义的类似于pojo类型 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("archimedes.jpg"));//创建并加载一个图片对象 } } }