python tk增加菜单项的便捷封装

发布时间 2023-07-11 22:36:56作者: 顺其自然,道法自然

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()