效果怎么样.
核心代码实现
- 1. 核心组件[MenuComputer]
import com.liangchao.futureworld.entity.MenuContent;
import com.liangchao.futureworld.frame.App;
import com.liangchao.futureworld.frame.R;
import com.liangchao.futureworld.utils.Logs;
import com.liangchao.futureworld.utils.RS;
import com.liangchao.futureworld.utils.javafx.FxUtil;
import com.liangchao.futureworld.utils.javafx.JfxExtends;
import com.liangchao.futureworld.utils.javafx.ui.MenuAssemblyHandle;
import de.felixroske.jfxsupport.AbstractFxmlView;
import de.jensd.fx.glyphs.GlyphIcons;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import javafx.event.Event;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Accordion;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.*;
import java.util.List;
/**
* 主菜单组件容器对象 @Program: win-manager
*
* @Author: LCH
* @Create: 2020-10-01 16:49 @Description:
* @Version:
*/
public class MenuComputer {
private static final String LEFT_ROOT_NAME = "leftRoot"; //左侧根容器
private Pane pane; // 菜单主容器
private BorderPane borderPane; // 内容根容器
private List<MenuContent> list; // 菜单数据源
private Object source; // 加载FXML 容器数据
private Object chilerSource; // 加载FXML 容器数据 子菜单面板
/**
* 菜单组件对象
*
* @param pane 菜单容器
* @param list 菜单数据对象
* @param borderPane 右侧内容根容器
*/
public MenuComputer(Pane pane, List<MenuContent> list, BorderPane borderPane) {
this.pane = pane;
this.list = list;
this.borderPane = borderPane;
initNodes();
}
/**
* 执行事件调用
*/
private void action(Pane box, MenuContent menu, Pane parent) {
if (menu == null || menu.getMethod() == null) {
return;
}
this.select(parent, box);
this.execute(menu.getHandleClassBeanName(), menu.getMethod(), null);
}
/**
* 绑定菜单数据
*/
public void binds() {
if (list == null || list.size() == 0 || pane == null || borderPane == null) {
return;
}
// 创建菜单列表
VBox singleMenuBox = new VBox();
singleMenuBox.getStyleClass().add("singleMenuBox");
Accordion accordion = new Accordion();
ScrollPane scrollPane = new ScrollPane(new VBox(accordion, singleMenuBox));
scrollPane.setMinWidth(0);
scrollPane.getStyleClass().addAll(LEFT_ROOT_NAME, "scroll-vertical");
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
this.pane.getChildren().add(scrollPane);
AnchorPane anchorPane;
TitledPane titledPane;
int ii = 0;// 单个菜单索引
//添加弧形菜单
for (int i = 0; i < list.size(); i++) {
MenuContent parent = list.get(i);
// 子节点 有子节点容器
if (parent.getNode() != null) {
VBox vbox = new VBox();
vbox.getStyleClass().add("titledPaneVbox");
vbox.prefWidthProperty().bind(scrollPane.widthProperty());
anchorPane = new AnchorPane(vbox);
anchorPane.getStyleClass().add("menuBoxPane");
titledPane = new TitledPane();
titledPane.setContent(anchorPane);
titledPane.setText(parent.getName());
accordion.getPanes().add(titledPane);
for (int j = 0; j < parent.getNode().size(); j++) {
MenuContent menuContent = parent.getNode().get(j);
this.menu(vbox, menuContent, j);
}
}
// 单个节点
else {
this.menu(singleMenuBox, parent, ii);
ii++;
}
}
}
/**
* 构建菜单事件容器对象
*
* @param vbox 父容器
* @param menuContent 菜单数据
* @param j 序列
*/
public void menu(VBox vbox, MenuContent menuContent, int j) {
Enum<? extends GlyphIcons> ficon = menuContent.getIcon();
Node icon = R.icon(ficon != null ? ficon : FontAwesomeIcon.CUBE);
icon.getStyleClass().add("textIcon");
// 菜单名称
HBox hboxlable = new HBox(new Label(menuContent.getName()));
hboxlable.setAlignment(Pos.CENTER_LEFT);
HBox.setHgrow(hboxlable, Priority.ALWAYS);
// 序列号
HBox indexbox = new HBox(new Label(j < 9 ? "0" + (j + 1) : (j + 1) + ""));
indexbox.getStyleClass().add("indexbox");
indexbox.setAlignment(Pos.CENTER_LEFT);
// 右侧标记容器
HBox rhbox = new HBox(new Label(RS.RM.nextInt(1000) + ""));
rhbox.getStyleClass().add("rhbox");
rhbox.setAlignment(Pos.CENTER_RIGHT);
HBox hbox = new HBox();
hbox.setAlignment(Pos.CENTER_LEFT);
hbox.getStyleClass().add("menuHbox");
hbox.getChildren().add(indexbox);
hbox.getChildren().add(icon);
hbox.getChildren().add(hboxlable);
hbox.getChildren().add(rhbox);
vbox.getChildren().add(hbox);
HBox.setHgrow(hboxlable, Priority.ALWAYS);
hbox.setOnMouseClicked(event -> {
//添加事件
switch (menuContent.getTypes()) {
case FXML:
fxml(hbox, vbox, borderPane, menuContent);
break;
case ACTION:
action(hbox, menuContent, pane);
break;
case LINK:
link(hbox, menuContent, pane, false);
break;
case MENU_LIST:
//只存在主菜单->子菜单两层数据
throw new RuntimeException("子菜单数据信息无效,只存在主菜单->子菜单两层数据");
}
});
}
/**
* 设置内容区域数据
*
* @param bean Class||fxml 路径
* @param shrink 是否执行收缩/展开; true:展开;false:收缩
* @param openParam 打开窗口前传递参数对象
*/
public void bindsContent(Object bean, boolean shrink, Object... openParam) {
JfxExtends.beforcHandle(source);
AbstractFxmlView fxmlView = null;
// class 参数
if (bean instanceof Class) {
fxmlView = (AbstractFxmlView) App.getBean((Class) bean);
}
// bean name参数
else {
fxmlView = (AbstractFxmlView) App.getBean(bean.toString());
}
if (fxmlView != null) {
// 添加到容器面板
borderPane.setCenter((fxmlView.getView()));
FxUtil.loadingStyleSheel(fxmlView);
// 更新宽度
if (fxmlView.getView() instanceof Pane) {
Pane pane = (Pane) fxmlView.getView();
// 指定根容器样式定义
pane.getStyleClass().add(RS.PAGE_STYLE_CLASS_KEY);
FxUtil.initAnchorPane(pane, 20d);
//设置边距
pane.setPadding(new Insets(5));
}
JfxExtends.afterHandle(fxmlView, openParam);
source = fxmlView;
}
}
/**
* 设置内容区域数据
*
* @param bean Class||fxml 路径
* @param regionPane 右侧数据容器
*/
public void bindsContent(Object bean, Region regionPane, Object openParam) {
JfxExtends.beforcHandle(source);
AbstractFxmlView fxmlView = null;
// class 参数
if (bean instanceof Class) {
fxmlView = (AbstractFxmlView) App.getBean((Class) bean);
}
// bean name参数
else {
fxmlView = (AbstractFxmlView) App.getBean(bean.toString());
}
if (fxmlView != null) {
Node bodyNode = null;
if (fxmlView.getPresenter() instanceof MenuAssemblyHandle) {
Logs.msg(fxmlView.getView() + " MenuAssemblyHandle 容器处理完成.");
MenuAssembly menuAssembly = new MenuAssembly();
// 设置调用控制器
menuAssembly.setController(fxmlView.getPresenter());
// 绑定菜单
menuAssembly.addMenus(((MenuAssemblyHandle) fxmlView.getPresenter()).bindMenus());
// 给控制器设置当前组件对象
((MenuAssemblyHandle) fxmlView.getPresenter()).drive(menuAssembly);
// 加一个AnchorPane外壳
VBox box = new VBox(menuAssembly.getNode(), fxmlView.getView());
AnchorPane temp = new AnchorPane();
temp.getChildren().add(box);
FxUtil.initAnchorPane(box, 0d, 0d, 0d, 0d);
bodyNode = temp;
} else {
bodyNode = fxmlView.getView();
}
// 添加到容器面板
if (regionPane instanceof BorderPane) {
((BorderPane) regionPane).setCenter(bodyNode);
} else if (regionPane instanceof ScrollPane) {
((ScrollPane) regionPane).setContent(bodyNode);
} else if (regionPane instanceof Pane) {
((Pane) regionPane).getChildren().clear();
((Pane) regionPane).getChildren().add(bodyNode);
} else {
throw new RuntimeException("regionPane is not ScrollPane or Pane , not is add");
}
FxUtil.loadingStyleSheel(fxmlView);
// 更新宽度
if (bodyNode instanceof Pane) {
Pane pane = (Pane) bodyNode;
// 指定根容器样式定义
pane.getStyleClass().add(RS.PAGE_STYLE_CLASS_KEY);
FxUtil.initAnchorPane(pane, 0d);
//设置边距
// pane.setPadding(new Insets(5));
//高度
pane.prefWidthProperty().bind(regionPane.widthProperty());
pane.prefHeightProperty().bind(regionPane.heightProperty());
// 当前节点下第一级节点pane样式
if (pane.getChildren().size() > 0) {
pane.getChildren().get(0).getStyleClass().add(RS.CONTENT_PANES);
}
}
JfxExtends.afterHandle(fxmlView, openParam);
source = fxmlView;
}
}
/**
* 主容器加载数据面板
*
* @param fxml fxml 路径
* @param openParam 打开加载参数
*/
public void bindContent(Object fxml, Object openParam) {
this.bindsContent(fxml, borderPane, openParam);
}
/**
* 置空内容容器对象
*/
public void cleanContent() {
JfxExtends.beforcHandle(chilerSource);
JfxExtends.beforcHandle(source);
borderPane.setCenter(null);
source = null;
chilerSource = null;
}
/**
* 执行事件处理
*
* @param beanName 受管bean名称
* @param methodName 调用方法名称
* @param event 事件对象
*/
public void execute(String beanName, String methodName, Event event) {
try {
if (methodName != null && beanName != null) {
ExecuteHandle.execute(App.getBean(beanName), methodName, event);
} else if (methodName != null && beanName == null) {
ExecuteHandle.execute(methodName, event);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 内容面板加载FXML页面
*/
private void fxml(Pane box, MenuContent menu, Pane parent) {
if (menu == null || menu.getData() == null) {
return;
}
this.select(parent, box);
// 设置数据内容
this.bindsContent(menu.getData(), true);
}
/**
* 子界面菜单加载FXML面板对象
*
* @param box 当前控件
* @param menu 菜单数据
* @param parent box 父容器
* @param rightBody 右侧容器
*/
public void fxml(Pane box, Pane parent, Pane rightBody, MenuContent menu) {
if (menu == null || menu.getData() == null || parent == null || rightBody == null) {
return;
}
this.select(parent, box);
// 设置数据内容
this.bindsContent(menu.getData(), rightBody, null);
}
/**
* 初始化容器
*/
private void initNodes() {
//只清理菜单
this.pane.getChildren().clear();
}
/**
* 打开连接
*/
private void link(Pane box, MenuContent menu, Pane parent, boolean isChiler) {
if (menu == null || menu.getData() == null) {
return;
}
this.select(parent, box);
JfxExtends.beforcHandle(isChiler ? chilerSource : source);
// 浏览器专用视图 InternetExplorerUI
// bindsContent(InternetExplorerUI.class, false, menu.getData());
}
/**
* 界面有子菜单对象
*/
private void list(Pane box, MenuContent menu, Pane parent) {
if (menu == null) {
return;
}
this.select(parent, box);
//创建右侧子菜单
// bindChilerMenus(menu.getNode(), chilerPaneBox);
}
/**
* 设置选中菜单
*
* @param select 选中box
*/
public void select(Pane select) {
if (pane == null || select == null) {
return;
}
for (Node node : this.pane.getChildren()) {
if (node instanceof Pane) {
node.getStyleClass().remove(RS.STYLE_CLASS_SELECT_KEY);
//选中
if (node.equals(select)) {
node.getStyleClass().add(RS.STYLE_CLASS_SELECT_KEY);
}
}
}
}
/**
* 设置选中菜单
*
* @param pane 指定容器pane
* @param select 容器子节点当前选中节点
*/
public void select(Pane pane, Pane select) {
if (pane == null || select == null) {
return;
}
for (Node node : pane.getChildren()) {
if (node instanceof Pane) {
node.getStyleClass().remove(RS.STYLE_CLASS_SELECT_KEY);
//选中
if (node.equals(select)) {
node.getStyleClass().add(RS.STYLE_CLASS_SELECT_KEY);
}
}
}
}
}
- 2. 核心组件[MenuContent]
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.*;
import java.util.LinkedList;
import java.util.List;
/**
* @Program: audit-cms
* @Author: LCH
* @Create: 2020-10-07 21:12
* @Description:
* @Version:
*/
@Setter
@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
public class MenuContent extends FontIcon {
private Integer id; //ID
private String name; //菜单名称
private MenuType types;//菜单类型
private String method; //执行方法名称
private String handleClassBeanName;//执行方法类Bean名称
private String data;//数据对象
private Object tip;//子菜单右侧数据
private String explains;
private List<MenuContent> node = new LinkedList<>();//子菜单组
public MenuContent(Integer id, String name, String icon, MenuType types, String method, String handleClassBeanName, String data, Object tip, String explains, List<MenuContent> node) {
this.id = id;
this.name = name;
this.icon = icon;
this.types = types;
this.method = method;
this.handleClassBeanName = handleClassBeanName;
this.data = data;
this.tip = tip;
this.explains = explains;
this.node = node;
}
/**
* 构建 GlyphIcons 图标
*/
public MenuContent(Integer id, String name, Object icon, MenuType types, String method, String handleClassBeanName, String data, Object tip, String explains, List<MenuContent> node) {
this.id = id;
this.name = name;
this.types = types;
this.method = method;
this.handleClassBeanName = handleClassBeanName;
this.data = data;
this.tip = tip;
this.explains = explains;
this.node = node;
this.setIcon(icon);
}
}