使用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);//向图像编辑主菜单添加挂载对应的子菜单和菜单选项
————————————
适当的时机禁用与启用 无特效选项
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"));//创建并加载一个图片对象
}
}
}