Python界面编程Tkinter创建菜单:窗口菜单、工具菜单、右键菜单-右键菜单设置

窗口菜单

Tkinter 为创建菜单提供Menu 类,该类既能实现菜单,又能实现上下文菜单(右键菜单)

Menu类创建菜单提供相关方法:

  • add_cascade() 添加菜单
  • add_command() 添加菜单项
  • add_checkbutton() 添加复选框菜单项
  • add_radiobutton() 添加单选钮菜单项
  • add_separator() 添加菜单分隔条

方法对应参数:

  • label:指定菜单项的文本
  • command:为菜单项绑定的事件处理函数
  • image:指定菜单项的图标
  • compound:指定菜单项中图标位于文字的哪个方位

使用Menu创建窗口菜单示例

# -*- coding:utf-8 -*-
from tkinter import *
# 导入ttk
from tkinter import ttk
from tkinter import messagebox
class App(object):
def __init__(self, mw):
self.mw = mw
self.init_menu()
def init_menu(self):
self.filenew_icon = PhotoImage(file='image/filenew.png')
self.fileopen_icon = PhotoImage(file='image/fileopen.png')

menubar = Menu(self.mw)
# 将menu设置为窗口的菜单条
self.mw['menu'] = menubar
# 创建file_menu菜单,并放入menubar中
file_menu = Menu(menubar, tearoff=0)
# 添加file_menu菜单
menubar.add_cascade(label='文件', menu=file_menu)
# file_menu添加菜单项
file_menu.add_command(label="新建", command = None,image=self.filenew_icon, compound=LEFT)
file_menu.add_command(label="打开", command = None,image=self.fileopen_icon, compound=LEFT)
# 为file_menu添加分隔条
file_menu.add_separator()

# 为file_menu创建子菜单
sub_menu = Menu(file_menu, tearoff=0)
# 添加sub_menu子菜单
file_menu.add_cascade(label='选择性别', menu=sub_menu)
self.genderVar = StringVar()
# 为sub_menu子菜单添加菜单项
for im in ['男', '女', '保密']:
sub_menu.add_radiobutton(label=im, command=self.choose_gender, variable=self.genderVar, value=im)
# 创建lang_menu菜单,并放入menubar中
lang_menu = Menu(menubar, tearoff=0)
# 添加lang_menu菜单
menubar.add_cascade(label='选择语言', menu=lang_menu)
self.langVars = [StringVar(), StringVar(), StringVar(), StringVar()]
# 为lang_menu菜单添加菜单项
for i, im in enumerate(('Python', 'Java','Golang', 'C++')):
lang_menu.add_checkbutton(label=im, command=self.choose_lang,
onvalue=im, variable=self.langVars[i])
def choose_gender(self):
messagebox.showinfo(message=('选择的性别为: %s' % self.genderVar.get()))
def choose_lang(self):
rt_list = [e.get() for e in self.langVars]
messagebox.showinfo(message=('选择的语言为: %s' % ','.join(rt_list)))
if __name__ == "__main__":
mw = Tk()
mw.title("窗口菜单")
mw.geometry('200x100')
mw.iconbitmap('image/logo.ico')
App(mw)
mw.mainloop()
看懂上面的示例,就会基于该示例,创建更复杂的窗口菜单

 

工具条菜单

Tkinter没有工具菜单组件,通过Frame+Button实现工具条,即Frame为工具条,Button为工具条上的按钮,示例代码如下:

# -*- coding:utf-8 -*-
from tkinter import *
from tkinter import ttk
from collections import OrderedDict
class App(object):
def __init__(self, mw):
self.mw = mw
self.initWidgets()
def initWidgets(self):
# 初始化图标
self.init_icons()
# 调用init_menu初始化菜单
self.init_menu()
# 调用init_toolbar初始化工具条
self.init_toolbar()
# 创建、添加左边Frame容器
leftframe = ttk.Frame(self.mw, width=40)
leftframe.pack(side=LEFT, fill=Y,expand=True)
# 在左边窗口放一个Listbox
lb = Listbox(leftframe, font=('arial', 20))
lb.pack(fill=Y, expand=YES)
for s in ('Python', 'JavaScript', 'Golang', 'Java'):
lb.insert(END, s)
# 创建、添加右边Frame容器
mainframe = ttk.Frame(self.mw)
mainframe.pack(side=LEFT, fill=BOTH, expand=True)
text = Text(mainframe, width=40, font=('arial', 16))
text.pack(side=LEFT, fill=BOTH)
scroll = ttk.Scrollbar(mainframe)
scroll.pack(side=LEFT,fill=Y)
scroll['command'] = text.yview
text.configure(yscrollcommand=scroll.set)
def init_menu(self):
"""初始化菜单"""
# 定义3个菜单
menus = ('文件', '编辑', '帮助')
# 定义菜单数据,(dict,dict,dict...)
items = (OrderedDict([
# 名称,图标,处理函数
('新建', (self.mw.filenew_icon, None)),
('打开', (self.mw.fileopen_icon, None)),
('保存', (self.mw.save_icon, None)),
('另存为...', (self.mw.saveas_icon, None)),
('-1', (None, None)),
('退出', (self.mw.signout_icon, None)),
]),
OrderedDict([('撤销',(None, None)),
('重做',(None, None)),
('-1',(None, None)),
('剪切',(None, None)),
('复制',(None, None)),
('粘贴',(None, None)),
('删除',(None, None)),
('选择',(None, None)),
('-2',(None, None)),
# 二级菜单
('更多', OrderedDict([
('显示数据',(None, None)),
('显示统计',(None, None)),
('显示图表',(None, None))
]))
]),
OrderedDict([('帮助主题',(None, None)),
('-1',(None, None)),
('关于', (None, None))]))
# 使用Menu创建菜单条
menubar = Menu(self.mw)
# 为窗口配置菜单条
self.mw['menu'] = menubar
# 遍历menus元组
for i, m_title in enumerate(menus):
# 创建菜单
m = Menu(menubar, tearoff=0)
# 添加菜单
menubar.add_cascade(label=m_title, menu=m)
# 将当前正在处理的菜单数据赋值给tm
tm = items[i]
# 遍历OrderedDict,默认只遍历它的key
for label in tm:
# 二级级菜单,如果value是OrderedDict,说明是二级菜单
if isinstance(tm[label], OrderedDict):
# 创建子菜单、并添加子菜单
sm = Menu(m, tearoff=0)
m.add_cascade(label=label, menu=sm)
sub_dict = tm[label]
# 再次遍历子菜单对应的OrderedDict,默认只遍历它的key
for sub_label in sub_dict:
if sub_label.startswith('-'):
# 添加分隔条
sm.add_separator()
else:
# 添加菜单项
sm.add_command(label=sub_label,image=sub_dict[sub_label][0],
command=sub_dict[sub_label][1], compound=LEFT)
elif label.startswith('-'):
# 一级菜单:添加分隔条
m.add_separator()
else:
# 一级菜单:添加菜单项
m.add_command(label=label,image=tm[label][0],
command=tm[label][1], compound=LEFT)
def init_icons(self):
self.mw.filenew_icon = PhotoImage(file='image/filenew.png')
self.mw.fileopen_icon = PhotoImage(file='image/fileopen.png')
self.mw.save_icon = PhotoImage(file='image/filesave.png')
self.mw.saveas_icon = PhotoImage(file='image/saveas.png')
self.mw.signout_icon = PhotoImage(file='image/quit.png')

# 生成工具条
def init_toolbar(self):
toolframe = Frame(self.mw, height=43, bg='lightgray')
toolframe.pack(fill=X)
frame = ttk.Frame(toolframe)
frame.pack(side=LEFT)
icons = [
self.mw.filenew_icon,
self.mw.fileopen_icon,
self.mw.save_icon,
self.mw.saveas_icon,
self.mw.signout_icon
]
for i, img in enumerate(icons):
ttk.Button(frame, width=20, image=img,
command=None).grid(row=0, column=i, padx=1, pady=1, sticky=E)
if __name__ == "__main__":
mw = Tk()
mw.title("工具条菜单")
mw.iconbitmap('image/logo.ico')
App(mw)
mw.mainloop()

右键菜单

使用Menu类实现右键菜单,需要先创建菜单,然后为目标组件的右击事件绑定处理函数,当用户单击鼠标右键时,调用Menu类实例的post()方法即可在指定位置弹出右键菜单

实现右键菜单

# -*- coding:utf-8 -*-
import functools
from tkinter import *
# 导入ttk
from tkinter import ttk
from collections import OrderedDict
class App(object):
def __init__(self, mw):
self.mw = mw
self.initWidgets()
def initWidgets(self):
self.text = Text(self.mw, height=12, width=60,
foreground='darkgray',
font=('arial', 12),
spacing2=8, # 设置行间距
spacing3=12) # 设置段间距
self.text.pack()
st = '雷那网,\n一个有温度的Python兴趣屋'
self.text.insert(END, st)
# 为text组件的右键单击事件绑定处理函数
self.text.bind('<Button-3>', self.popup)
# 创建Menu对象
self.popup_menu = Menu(self.mw, tearoff = 0)
self.my_items = (OrderedDict([('超大', 16), ('大',14), ('中',12),('小',10), ('超小',8)]),
OrderedDict([('红色','red'), ('绿色','green'), ('蓝色', 'blue')]))
for i,k in enumerate(['字体大小','颜色']):
m = Menu(self.popup_menu, tearoff = 0)
# 添加子菜单
self.popup_menu.add_cascade(label=k ,menu = m)
# 遍历OrderedDict的key(默认就是遍历key)
for im in self.my_items[i]:
m.add_command(label=im, command=functools.partial(self.choose, x=im))
def popup(self, event):
# 在指定位置显示菜单
self.popup_menu.post(event.x_root,event.y_root)

def choose(self, x):
# 如果用户选择修改字体大小的子菜单项
if x in self.my_items[0].keys():
# 改变字体大小
self.text['font'] = ('微软雅黑', self.my_items[0][x])
# 如果用户选择修改颜色的子菜单项
if x in self.my_items[1].keys():
# 改变颜色
self.text['foreground'] = self.my_items[1][x]
if __name__ == "__main__":
mw = Tk()
mw.title("右键菜单")
App(mw)
mw.mainloop()
posted @ 2022-06-22 16:15  苍月代表我  阅读(2285)  评论(0)    收藏  举报