python tk增加菜单项的便捷封装
TK增加菜单项的编码是比较复杂的, 为方便使用, 我做了一下封装, 用户使用场景:
root = tk.Tk()
AddMenuItem(root,'File.New.Close',lambda:print('111'))
AddMenuItem(root,'File.Hzq',lambda:print('abc'))
root.mainloop()
实现源码:
'''Tk扩展'''
import tkinter as tk
class _Vars:
MenuDictName = 'MenuDict' # 存放菜单相关的对象字典
pass
def AddMenuItem(window:tk.Tk,name:str,action:callable=None):
'''
增加一个菜单项;
name: 形如: 'File.New', 支持多级菜单, 名字用'.'分割
action: void f(), 菜单项的回调函数
'''
menus = _GetMenuDict(window)
if name in menus: return
# 创建顶级菜单
if '.' not in name: _CreateCascadeMenu(window,name); return
# 把形如'File.New.Close'分解为'File.New','Close'
cascadeMenuName,menuItemName = name.rsplit('.', 1)
cascadeMenu = _GetCascadeMenu(window,cascadeMenuName)
if action==None: cascadeMenu.add_command(label=menuItemName)
else: cascadeMenu.add_command(label=menuItemName,command=action)
def _CreateCascadeMenu(window:tk.Tk,name:str)->tk.Menu:
'''创建层级菜单'''
menus = _GetMenuDict(window)
# 顶级菜单项的处理
if '.' not in name:
menubar = _GetMenubar(window)
menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label=name, menu=menu)
menus[name] = menu
return menu
# 把形如'File.New.Close'分解为'File.New','Close'
upMenuName, curMenuName = name.rsplit('.', 1)
upMenu = _GetCascadeMenu(window,upMenuName)
curMenu = tk.Menu(upMenu, tearoff=0)
upMenu.add_cascade(label=curMenuName, menu=curMenu)
menus[name] = curMenu
return curMenu
def _GetCascadeMenu(window:tk.Tk,name:str)->tk.Menu:
'''获得形如'File.New'的cascadeMenu对象'''
menus = _GetMenuDict(window)
if name not in menus: _CreateCascadeMenu(window,name)
return menus[name]
def _GetMenubar(window:tk.Tk)->tk.Menu:
'''获得菜单栏'''
menus = _GetMenuDict(window)
if '.' not in menus:
menubar = tk.Menu(window)
menus['.'] = menubar
window.config(menu=menubar)
return menus['.']
def _GetMenuDict(window:tk.Tk)->dict:
'''获得存放菜单相关对象的字典'''
if not hasattr(window,_Vars.MenuDictName):
setattr(window,_Vars.MenuDictName,{})
menus = getattr(window,_Vars.MenuDictName)
return menus
root = tk.Tk()
AddMenuItem(root,'File.New.Close',lambda:print('111'))
AddMenuItem(root,'File.Hzq',lambda:print('abc'))
root.mainloop()