今晚苦思如何通过配置的形式可以无限增加菜单的层级,虽然有思路通过递归的算法,虽然知道递归算法,但是只知其名,不知其原理,今天抱着尝试的态度,果然出乎意料,可以让菜单的层级无限增加。
效果展示
配置表
QH_Number | QH_Menu_ID | QH_Menu_Qicon | QH_Menu_Name | QH_Menu_Letters | QH_Menu_Shortcut | QH_Menu_Separator | QH_Menu_Superior | QH_Menu_Is_late | QH_Menu_Rank | QH_Menu_Method | QH_StatusBar_Method | QH_Menu_Description |
序号 | 菜单ID | 图标 | 菜单名称 | 菜单字母 | 快捷键 | 分割线 | 上级菜单 | 是否末级 | 级数 | 方法 | 方法-状态栏 | 说明 |
1 | QH_File | 文件 | F | N | 1 | |||||||
2 | QH_Editor | 编辑 | E | N | 1 | |||||||
3 | QH_Test01 | Test01 | T | N | 1 | |||||||
4 | QH_Test02 | Test02 | T | N | 1 | |||||||
5 | QH_Test03 | Test03 | T | N | 1 | |||||||
11 | QH_File_New | qh_ui\icon\new.png | 新建 | N | Ctrl+N | Y | QH_File | Y | 2 | self.qh_act_new_triggered | QH_File_New.hovered.connect(self.qh_act_new_hovered) | |
12 | QH_File_Open | qh_ui\icon\open.png | 打开 | O | Ctrl+O | QH_File | Y | 2 | self.qh_act_open_triggerd | QH_File_Open.hovered.connect(self.qh_act_open_hovered) | ||
13 | QH_File_Save | qh_ui\icon\save.png | 保存 | S | Ctrl+S | Y | QH_File | Y | 2 | self.qh_act_save_triggerd | QH_File_Save.hovered.connect(self.qh_act_save_hovered) | |
14 | QH_File_Exit | qh_ui\icon\exit.png | 退出 | E | Ctrl+E | QH_File | Y | 2 | self.close | QH_File_Exit.hovered.connect(self.qh_act_exit_hovered) | ||
15 | QH_Editor_Copy | 复制 | C | Ctrl+C | QH_Editor | Y | 2 | self.qh_planintext.copy | QH_Editor_Copy.hovered.connect(self.qh_act_copy_hovered) | |||
16 | QH_Editor_Cut | 剪切 | X | Ctrl+X | QH_Editor | Y | 2 | self.qh_planintext.cut | QH_Editor_Cut.hovered.connect(self.qh_act_cut_hovered) | |||
17 | QH_Editor_Paste | 粘贴 | P | Ctrl+P | QH_Editor | Y | 2 | self.qh_planintext.paste | QH_Editor_Paste.hovered.connect(self.qh_act_paste_hovered) | |||
18 | QH_Test01_A | QH_Test01_A | A | QH_Test01 | Y | 2 | ||||||
19 | QH_Test01_B | QH_Test01_B | B | QH_Test01 | N | 2 | ||||||
20 | QH_Test01_B_A | QH_Test01_B_A | A | QH_Test01_B | Y | 3 | self.close | |||||
21 | QH_Test02_A | QH_Test02_A | QH_Test02 | N | 2 | |||||||
22 | QH_Test02_A_A | QH_Test02_A_A | QH_Test02_A | N | 3 | |||||||
23 | QH_Test02_A_A_A | QH_Test02_A_A_A | QH_Test02_A_A | Y | 4 | self.close |
代码
import sys
import os
from PyQt5.QtWidgets import QApplication,QWidget,QAction,QMenuBar,\
QMenu,QPlainTextEdit,QVBoxLayout,QFileDialog,QToolButton,\
QToolBar,QFontComboBox,QComboBox,QStatusBar,QLabel
from PyQt5.QtGui import QIcon
import pandas as qh_pd
class Qh_MyWindow(QWidget):
def __init__(self,qh_parent = None):
super().__init__(qh_parent)
self.setWindowTitle("文本编辑器,阙辉")
self.resize(900,600)
self.qh_setupUI()
def qh_setupUI(self):
qh_menubar = QMenuBar()
qh_toolbar = QToolBar()
self.qh_statusbar = QStatusBar()
self.qh_planintext = QPlainTextEdit()
qh_vlayput = QVBoxLayout(self)
qh_vlayput.addWidget(qh_menubar)
qh_vlayput.addWidget(qh_toolbar)
qh_vlayput.addWidget(self.qh_planintext)
qh_vlayput.addWidget(self.qh_statusbar)
qh_act_newt = qh_toolbar.addAction(QIcon(r"qh_ui\icon\new.png"), "新建(&N)")
qh_act_opent = qh_toolbar.addAction(QIcon(r"qh_ui\icon\open.png"), "打开(&O)")
qh_act_savet = qh_toolbar.addAction(QIcon(r"qh_ui\icon\save.png"), "保存(&S)")
qh_act_exitt = qh_toolbar.addAction(QIcon(r"qh_ui\icon\exit.png"), "新建(&E)")
qh_toolbar.addSeparator()
qh_act_copyt = qh_toolbar.addAction("复制(&C)")
qh_act_cutt = qh_toolbar.addAction("剪切(&X)")
qh_act_pastet = qh_toolbar.addAction("粘贴(&P)")
self.fontC = QFontComboBox()
self.fontC.setFixedWidth(100)
qh_toolbar.addWidget(self.fontC)
self.qh_planintext.setFont(self.fontC.currentFont())
self.fontC.currentFontChanged.connect(self.qh_planintext.setFont)
self.combo = QComboBox(self)
for i in range(5, 50):
self.combo.addItem(str(i))
self.combo.setCurrentText("15")
qh_toolbar.addWidget(self.combo)
self.combo.currentIndexChanged.connect(self.qh_combo_change_size)
# 获取配置数据 form excel
qh_excel_name = "QH_Menu_Setting.xlsx"
qh_sheet = "QH_MENU"
qh_df = qh_pd.read_excel(io=qh_excel_name, sheet_name=qh_sheet)
qh_df.fillna("", inplace=True) # 替换一级为空
qh_df_01 = qh_df[(qh_df["QH_Menu_Superior"] == "")] # 获取一级菜单
for qh_i, qh_row in qh_df_01.iterrows():
#一级菜单
QH_Menu_ID = qh_row["QH_Menu_ID"] # 菜单ID
QH_Menu_Name = qh_row["QH_Menu_Name"] # 菜单名称
QH_Menu_Letters = qh_row["QH_Menu_Letters"] # 菜单字母
# 判断是否加字母
if QH_Menu_Letters != "":
qh_menu_Name = "{}(&{})".format(QH_Menu_Name,QH_Menu_Letters)
# 执行创建菜单
globals()[QH_Menu_ID] = qh_menubar.addMenu(qh_menu_Name)
# 获取下级菜单
qh_row_menu01 = qh_df[(qh_df["QH_Menu_Superior"] == QH_Menu_ID)]
# 二级以后的菜单迭代生成
self.Qh_AddMenu_A(qh_df, qh_row_menu01)
qh_label = QLabel("版本号1.0,阙辉 ", self)
self.qh_statusbar.addPermanentWidget(qh_label)
def Qh_AddMenu_A(self,qh_df,qh_row_menu):
"""
一级以后的菜单递归生成 作者:阙辉
递归:自己还没理解递归是啥意思,只是尝试,没想到成功了,哈哈!
2022-09-05
:param qh_df:
:param qh_row_menu:
:return:
"""
# 有下级菜单才执行
if len(qh_row_menu) > 0:
for qh_i, qh_row in qh_row_menu.iterrows():
QH_Menu_ID = qh_row["QH_Menu_ID"] # 菜单ID
QH_Menu_Qicon = qh_row["QH_Menu_Qicon"] # 图标
QH_Menu_Name = qh_row["QH_Menu_Name"] # 菜单名称
QH_Menu_Letters = qh_row["QH_Menu_Letters"] # 菜单字母
QH_Menu_Shortcut = qh_row["QH_Menu_Shortcut"] # 快捷键
QH_Menu_Separator = qh_row["QH_Menu_Separator"] # 分割线
QH_Menu_Superior = qh_row["QH_Menu_Superior"] # 上级菜单
QH_Menu_Is_late = qh_row["QH_Menu_Is_late"] # 是否末级
QH_Menu_Rank = qh_row["QH_Menu_Rank"] # 级数
QH_Menu_Method = qh_row["QH_Menu_Method"] # 方法
QH_StatusBar_Method = qh_row["QH_StatusBar_Method"] # 状态栏方法
QH_Menu_Description = qh_row["QH_Menu_Description"] # 说明
# 判断是否加字母
if QH_Menu_Letters != "":
qh_menu_Name = "{}(&{})".format(QH_Menu_Name, QH_Menu_Letters)
else:
qh_menu_Name = QH_Menu_Name
# 判断是否末级 匹配对应方法
if QH_Menu_Is_late == "Y":
qh_add_type = "addAction"
else:
qh_add_type = "addMenu"
# 初始化 子语句
qh_add_menu01 = ""
# 图标处理
if QH_Menu_Qicon != "":
qh_add_menu01 = 'QIcon(r"{}"),'.format(QH_Menu_Qicon)
qh_add_menu01 = qh_add_menu01 + "'" + str(qh_menu_Name) + "'"
# 菜单方法处理
if QH_Menu_Method != "" and QH_Menu_Is_late == "Y":
qh_add_menu01 = qh_add_menu01 + "," + str(QH_Menu_Method)
# 快捷键处理
if QH_Menu_Shortcut!= "":
qh_add_menu01 = qh_add_menu01 + ",'" + str(QH_Menu_Shortcut) + "'"
# 组合执行语句
qh_add_menu = str(QH_Menu_Superior) + "." + str(qh_add_type) + "(" + str(qh_add_menu01) + ")"
print(qh_add_menu)
# 执行创建菜单
globals()[QH_Menu_ID] = eval(qh_add_menu)
# 是否加分隔条
if QH_Menu_Separator != "":
globals()[QH_Menu_Superior].addSeparator()
# 绑定状态栏方法
if QH_StatusBar_Method != "" and QH_Menu_Is_late == "Y":
eval(QH_StatusBar_Method)
# 获取下级菜单
qh_row_menu00 = qh_df[(qh_df["QH_Menu_Superior"] == QH_Menu_ID)]
#迭代 自己还没理解递归是啥意思 只是尝试,没想到成功了 哈哈!
self.Qh_AddMenu_A(qh_df, qh_row_menu00)
def qh_combo_change_size(self,qh_text):
qh_font = self.qh_planintext.font()
qh_font.setPixelSize(int(qh_text))
self.qh_planintext.setFont(qh_font)
def qh_act_new_triggered(self):
self.qh_planintext.clear()
def qh_act_open_triggerd(self):
qh_filename,filter = QFileDialog.getOpenFileName(self,"打开文件")
if os.path.exists(qh_filename):
self.qh_planintext.clear()
fb = open(qh_filename,"r",encoding="utf-8")
qh_str = fb.readlines()
for qh_i in qh_str:
# qh_i = qh_i.strip()
self.qh_planintext.appendPlainText(qh_i)
fb.close()
def qh_act_save_triggerd(self):
qh_filename, filter = QFileDialog.getSaveFileName(self, "打开文件")
qh_str = self.qh_planintext.toPlainText()
if qh_filename != "":
if os.path.exists(qh_filename):
fb = open(qh_filename, "wa", encoding="utf-8")
fb.writelines(qh_str)
fb.close()
else:
fb = open(qh_filename, "w", encoding="utf-8")
fb.writelines(qh_str)
fb.close()
def qh_act_new_hovered(self):
self.qh_statusbar.showMessage("新建文档",5000)
def qh_act_open_hovered(self):
self.qh_statusbar.showMessage("打开文档",5000)
def qh_act_save_hovered(self):
self.qh_statusbar.showMessage("保存文档",5000)
def qh_act_exit_hovered(self):
self.qh_statusbar.showMessage("退出文档",5000)
def qh_act_copy_hovered(self):
self.qh_statusbar.showMessage("复制选中内容",5000)
def qh_act_cut_hovered(self):
self.qh_statusbar.showMessage("剪切选中内容",5000)
def qh_act_paste_hovered(self):
self.qh_statusbar.showMessage("在光标位置处粘贴",5000)
if __name__ == "__main__":
qh_app = QApplication(sys.argv) # 创建应用实例
qh_MyWindows = Qh_MyWindow() # 创建窗口实例
qh_MyWindows.show() # 显示窗口
qh_n = qh_app.exec() # 执行exec()方法,进入事件循环,如果遇到窗口退出命令,返回整数qh_n
sys.exit(qh_n) # 通知python系统,结束程序运行