PySimpleGUI 菜单从 0 到专业导航:一个嵌套列表搞定所有菜单
2026/8/24 6:00:15 网站建设 项目流程

PySimpleGUI 菜单从 0 到专业导航:一个嵌套列表搞定所有菜单

【免费下载链接】PySimpleGUIPython GUIs for Humans! Create any GUI simple or complicated in a way that's intuitive. Launched in 2018. NEW for 2026 - the LGPL3 Version 6. Transforms tkinter, Qt, WxPython, and Remi into a simple, intuitive, and fun experience for both hobbyists and expert users.项目地址: https://gitcode.com/gh_mirrors/py/PySimpleGUI

做桌面程序绕不开一个问题:功能越来越多,用户靠什么找到它们?答案几乎总是——菜单。PySimpleGUI 的菜单系统把这件事做到了极简:不管是顶部菜单栏、右键弹出、按钮下拉还是换色定制,全部由同一种数据结构驱动。掌握这套 PySimpleGUI 菜单玩法,你的 Python GUI 导航就有了专业级的骨架。

![PySimpleGUI 应用窗口与菜单导航界面示意](https://raw.gitcode.com/gh_mirrors/py/PySimpleGUI/raw/bca6fea965c144ae9b832c6445a931cb7e7c68c1/images/for_readme/Demo Browser Search Close Attempted.jpg?utm_source=gitcode_repo_files)

一个典型的 PySimpleGUI 应用窗口:顶部导航、操作区、输出区各司其职

一个核心思想:菜单就是嵌套列表 🌲

整个 PySimpleGUI 菜单系统只有一个基本单元:嵌套列表。最外层是一个列表,每个元素是「顶栏标签 + 点击后展开的项目列表」的二元组;某个项目本身又是一个列表时,就向右弹出下一级子菜单——层级就是这么递归出来的。

menu_def = [ ['&报表', ['新建报表', '导入数据', '---', '&导出 Ctrl-E', '!打印']], ['&数据', ['查询', ['按客户', '按区域'], '刷新']], ['&帮助', ['关于::about_key']] ]

这段代码定义了三个顶层入口,其中「数据」下藏着一个二级子菜单。列表里有 5 个记号值得刻进记忆:

记号写法作用
&&导出定义 Alt 快捷键(Alt+X),界面上以下划线提示,事件里不会带出这个符号
::关于::about_key给菜单项起一个程序用的唯一 key,用户看不到它,事件循环里以它为准
---单独一项画一条分隔线,用来给相关命令分组
!!打印把该菜单项置灰禁用
Ctrl-导出 Ctrl-E纯文本提示快捷键(空格对齐),只是显示,不绑定真实按键

记住这张表,后面所有菜单类型的定义方式都不用再学。

从 0 搭出第一个菜单

三步走:定义 → 挂到布局 → 读事件。

第一步,定义就是上面那份menu_def,不用多说。

第二步,用sg.Menu把定义挂进 layout 的某一行,它就是窗口顶部的菜单栏:

layout = [ [sg.Menu(menu_def, tearoff=False, key='-BAR-')], [sg.Text('报表工作台主区域', size=(40, 1))], [sg.Output(size=(60, 10))] ] window = sg.Window('报表工作台', layout)

第三步,菜单选择走的是和其他控件一样的事件通道——window.read()返回的event就是被点击项的文本(注意&已被剥离):

while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'Quit'): break if event == '导出': sg.popup('导出任务已开始') elif event == 'about_key': # 带 :: 的项按 key 匹配 sg.popup('关于', '报表工作台 v1.0')

到这一步,一个能点、能分组、能弹子菜单的三级导航就完整跑起来了。

四种菜单,各管一段导航

同一种列表结构,四个「宿主」,各占一块领地。按场景选:

类型入口 API适合场景
顶部菜单栏sg.Menu(menu_def)放进 layout全局功能的主入口,用户第一眼找的地方
右键上下文菜单sg.Window(..., right_click_menu=...)与当前位置/对象相关的操作(复制、粘贴、属性)
按钮下拉菜单sg.ButtonMenu(文本, 定义)放进 layout工具栏,把一组命令收进一个按钮
自定义菜单栏sg.MenubarCustom(定义)放进 layout要品牌配色、或配合自定义标题栏时使用

右键菜单:给sg.Window传一个right_click_menu即可,结构仍是老样子(第一个标签不会被显示,放占位字符串即可):

ctx_menu = ['未使用', ['复制', '粘贴', '剪切', '---', '属性']] window = sg.Window('报表工作台', layout, right_click_menu=ctx_menu)

按钮菜单ButtonMenu是一个会弹出下拉列表的按钮,key方便你之后单独改它:

layout = [ [sg.ButtonMenu('工具', [['撤销', '重做', '---', '设置']], key='-TOOL-', text_color='blue')] ]

自定义菜单栏sg.Menu的顶栏本身没法换色(只有下拉面板可以换),想要整条菜单栏的品牌色就上MenubarCustom,它本质是一排拼接起来的 ButtonMenu,颜色、字体、内边距全归你管:

layout = [ [sg.MenubarCustom(menu_def, pad=0, key='-CUSTBAR-', bar_background_color='#2c3e50', bar_text_color='white', background_color='#34495e', text_color='white')] ]

PySimpleGUI 内置主题的视觉效果预览:换成 MenubarCustom 后,菜单风格就能跟着品牌走

让菜单活起来:动态更新与事件细节

菜单不是建完就定死的,运行中随时可以换。

整表替换。拿到 Menu 元素的 key 后调update,注意必须提交完整的菜单定义,不能只改其中一项:

# 用户登录某个受限角色后,把"查询"整个分支置灰 menu_def[1][1][0] = '!查询' window['-BAR-'].update(menu_def)

改动会在下一次window.read()/refresh时生效。ButtonMenuupdate同理,还能顺带改按钮文字、颜色、可见性。

事件细节,三个容易踩的约定:

  • 用户点的是文本,事件值就是文本(无&);给项加了::key后,事件值变成那个 key——两种匹配别混用。
  • !开头的项是禁用态,永远不会有事件回来,适合做「占位但未解锁」的功能。
  • 右键菜单的第一项(顶栏标签)只是占位,永远不会成为事件。

一个能直接跑的完整例子

把顶部菜单、右键菜单、按钮菜单和动态刷新放进同一个「报表工作台」,整段可运行:

import PySimpleGUI as sg menu_def = [ ['&报表', ['新建报表', '导出', '---', '退出::exit_key']], ['&数据', ['查询', ['按客户', '按区域'], '刷新::refresh']], ['&帮助', ['关于']] ] ctx_menu = ['未使用', ['复制', '粘贴', '剪切']] layout = [ [sg.Menu(menu_def, key='-BAR-')], [sg.Text('右键下方区域试试上下文菜单', size=(40, 1))], [sg.ButtonMenu('工具', [['撤销', '重做', '---', '设置']], key='-TOOL-')], [sg.Output(size=(60, 8))] ] window = sg.Window('报表工作台', layout, right_click_menu=ctx_menu) while True: event, values = window.read() if event in (sg.WIN_CLOSED, 'exit_key'): break if event == 'refresh': menu_def[1][1][0] = '!查询' # 刷新时临时禁用查询 window['-BAR-'].update(menu_def) else: print(f'菜单事件: {event}') window.close()

运行后依次试一遍:点「报表 → 导出」,在输出区右键看上下文菜单,点「工具」按钮看工具栏下拉,再点「数据 → 刷新」看菜单被动态置灰——四种形态与动态更新,全在这 30 行里。

少走弯路:常见坑与上手建议

坑:菜单整个不出现→ 检查menu_def是不是「每个顶层项都是 [标签, 列表] 的二元组」。最常见的是把项目直接写进最外层列表。

坑:点了菜单没有反应→ 事件值和带&的原文对不上。匹配时用不带&的文本,或者干脆给项加::key再按 key 匹配,一劳永逸。

坑:想改菜单栏颜色,参数却没用sg.Menu的颜色参数只作用于下拉面板,顶栏本身改不了。要换整条栏的配色,换成sg.MenubarCustom

坑:update 之后界面无变化→ 一是漏了「提交完整定义」,二是改完没有经过下一次window.read()refresh,界面不会自己刷新。

设计建议(来自大量真实应用的共识):

  • 层级压到 3 层以内,越深越没人点;
  • ---按功能分组,一组一隔;
  • 高频项给快捷键,&配 Alt,Ctrl-文本做提示;
  • 排序遵循「常用的靠前、相关的挨着」。

仓库里还有三份现成参考,直接打开就能读:

  • 四种菜单形态的完整演示:Demo_Menus.py
  • 自定义菜单栏(含配色与 tearoff):Demo_Menubar_Custom.py
  • 菜单 + 工具栏组合:Demo_Menu_With_Toolbar.py

下次再给程序加功能时,先别急着堆按钮:拿一份嵌套列表,把新功能塞进对应分支,导航自己会生长。

【免费下载链接】PySimpleGUIPython GUIs for Humans! Create any GUI simple or complicated in a way that's intuitive. Launched in 2018. NEW for 2026 - the LGPL3 Version 6. Transforms tkinter, Qt, WxPython, and Remi into a simple, intuitive, and fun experience for both hobbyists and expert users.项目地址: https://gitcode.com/gh_mirrors/py/PySimpleGUI

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询