正在尝试着做一个比较完善的画图软件,计划使用tkinter库中的canvas控件来做, 然后里面有涉及到菜单的使用,因此作为这个画图软件的附带产出物,整理成了本篇博文,分享给大家,一起研究研究,期待能对你工作带来启发和帮助。
不忘初心,方得始终,让我们一起共勉!
好的,言归正传,回归本篇博文的主题:python中tkinter窗口菜单的使用(OptionMenu控件和Menu控件)。
先从宏观上认识一下菜单,其实就是不外乎如下几个内容:
1、菜单的显示位置和绑定的父控件,即该菜单与那个控件绑定,并如何显示。
2、菜单的选项,即该菜单有哪些菜单项。
3、菜单项的事件响应绑定,即每个具体的菜单项与那个事件或者函数进行绑定。
4、按照业务逻辑进行绑定事件或函数的具体实现,每个不同的函数实现各自的业务逻辑,具体实现按需。
那么这里分别介绍两大类的控件,分别是OptionMenu控件和Menu控件。
一、OptionMenu控件
OptionMenu 组件用于构建一个带菜单的按钮,该菜单可以在按钮的四个方向上展开,展开方向可通过 direction 选项控制。 (其中:direction有'below','above','left','right','flush'这几种类型)
master 参数的作用与所有的 Tkinker 组件一样,指定将该组件放入哪个容器中。
variable:指定该按钮上的菜单与哪个变量绑定。
value:指定默认选择菜单中的哪一项。
values:Tkinter 将收集为此参数传入的多个值,为每个值创建一个菜单项。
kwargs:用于为 OptionMenu 配置选项。除前面介绍的常规选项之外,还可通过 direction 选项控制菜单的展开方向。
先初始化主窗口:
from tkinter import*
# 导入ttk
from tkinter import ttk
root =Tk()
root.title("OptionMenu测试")
root.geometry('300x200')
root.mainloop()
然后新建menu并绑定root,相关脚本如下:
sv =StringVar()
om = ttk.OptionMenu(root,
sv,# 绑定变量
'tkinter',# 设置初始选中值
'label',# 以下多个值用于设置菜单项
'text',
'entry',
'listbox',
'treeview',
'notebook',
command = change_option)# 绑定事件处理方法
om.pack(expand=Y)
然后添加响应函数,相关代码如下:
from tkinter import ttk,messagebox
def change_option(val):
print(sv.get(), val)
messagebox.showinfo(message=('你选择了:%s' % val))
最终运行效果如下:
二、Menu控件
Tkinter 为菜单提供了 Menu 类,该类既可代表菜单条,也可代表菜单,还可代表上下文菜单(右键菜单)。简单来说,Menu 类就可以搞定所有菜单相关内容。
程序可调用 Menu 的构造方法来创建菜单,在创建菜单之后可通过如下方法添加菜单项:
add_command():添加菜单项。
add_checkbutton():添加复选框菜单项。
add_radiobutton():添加单选钮菜单项。
add_separator():添加菜单分隔条。
上面的前三个方法都用于添加菜单项,因此都支持如下常用选项:
label:指定菜单项的文本。
command:指定为菜单项绑定的事件处理方法。
image:指定菜单项的图标。
compound:指定在菜单项中图标位于文字的哪个方位。
有了菜单之后,接下来就是如何使用菜单了。
菜单有两种用法:
1.在窗口上方通过菜单条管理菜单。
2.通过鼠标右键触发右键菜单(上下文菜单)。
(一)先实现菜单条管理的菜单。
实现菜单布局:
root =Tk()
root.title("菜单测试")
root.geometry('400x200')
menubar =Menu(root)
root['menu']= menubar
file_menu =Menu(menubar, tearoff=0)
menubar.add_cascade(label='文件', menu=file_menu)
lang_menu =Menu(menubar, tearoff=0)
menubar.add_cascade(label='格式', menu=lang_menu)
file_menu.add_command(label="新建", command = None)
file_menu.add_command(label="打开", command = None)
file_menu.add_command(label="保存", command = None)
file_menu.add_separator()
file_menu.add_command(label="退出", command = None)
lang_menu.add_command(label="字体", command = None)
lang_menu.add_command(label="颜色", command = None)
root.mainloop()
显示如下:
在主窗口增加多行文本框,相关脚本如下:
text =Text(root, height=12, width=60,
foreground='darkgray',
font=('微软雅黑',12),
spacing2=8,# 设置行间距
spacing3=12)# 设置段间距
text.pack(fill=BOTH,expand=Y)
st ='Tkinter 为菜单提供了 Menu 类,该类既可代表菜单条,也可代表菜单,还可代表上下文菜单(右键菜单)。简单来说,Menu 类就可以搞定所有菜单相关内容。\n'
text.insert(END, st)
显示如下:
实现响应函数:
def on_new():
text.delete(1.0,END)
def on_open():
localfile = filedialog.askopenfile(title='打开单个文件',
filetypes=[("文本文件","*.txt")],# 只处理的文件类型
initialdir='D:/')
if(localfile):
text.delete(1.0,END)
with open(localfile.name,'r',encoding='utf-8') as f:
txt = f.readlines()
text.insert(END,txt)
else:
msgbox.showinfo(message=('读取文件异常'))
def on_save():
localfile = filedialog.asksaveasfile(title='保存文件',
filetypes=[("文本文件", "*.txt")], # 只处理的文件类型
initialdir='D:/')
if(localfile):
txt = text.get(1.0,END)
print(txt)
with open(localfile.name,'w',encoding='utf-8') as f:
f.write(txt)
else:
msgbox.showinfo(message=('读取文件异常'))
def on_exit():
root.destroy()
实现text的滚动条显示:
scroll =Scrollbar(text, command=text.yview)
scroll.pack(side=RIGHT, fill=Y)
# 设置text2的纵向滚动影响scroll滚动条
text.configure(yscrollcommand=scroll.set)
text.configure(state=NORMAL)
运行效果如下:
(二)实现右键菜单
1、实现右键菜单项:
text.bind('<Button-3>', popup)
popup_menu = Menu(text, tearoff=0)
my_items = (OrderedDict([('超大', 16), ('大', 14), ('中', 12),
('小', 10), ('超小', 8)]),
OrderedDict([('红色', 'red'), ('绿色', 'green'), ('蓝色', 'blue')]))
i = 0
for k in ['字体大小', '颜色']:
m = Menu(popup_menu, tearoff=0)
popup_menu.add_cascade(label=k, menu=m)
# 遍历OrderedDict的key(默认就是遍历key)
for im in my_items[i]:
m.add_command(label=im, command=handlerAdaptor(choose, x=im))
i += 1
2、绑定响应函数:
def popup(event):
# 在指定位置显示菜单
popup_menu.post(event.x_root, event.y_root)
def choose(x):
# 如果用户选择修改字体大小的子菜单项
if x in my_items[0].keys():
# 改变字体大小
text['font'] = ('微软雅黑', my_items[0][x])
# 如果用户选择修改颜色的子菜单项
if x in my_items[1].keys():
# 改变颜色
text['foreground'] = my_items[1][x]
def handlerAdaptor(fun, **kwds):
return lambda fun=fun, kwds=kwds: fun(**kwds)
最终实现的效果如下:
好的,感谢关注,最终的一个较为完善的文本文件编辑软件就做好,完全实现了菜单项打开、保存和新建的功能,而且也实现了右键的保存功能,相关完整的代码如下:
from tkinter import *
# 导入ttk
from tkinter import ttk
from tkinter import messagebox as msgbox
from tkinter import filedialog
from collections import OrderedDict
def on_new():
text.delete(1.0,END)
def on_open():
localfile = filedialog.askopenfile(title='打开单个文件',
filetypes=[("文本文件","*.txt")],# 只处理的文件类型
initialdir='D:/')
if(localfile):
text.delete(1.0,END)
with open(localfile.name,'r',encoding='utf-8') as f:
txt = f.readlines()
text.insert(END,txt)
else:
msgbox.showinfo(message=('读取文件异常'))
def on_save():
localfile = filedialog.asksaveasfile(title='保存文件',
filetypes=[("文本文件", "*.txt")], # 只处理的文件类型
initialdir='D:/')
if(localfile):
txt = text.get(1.0,END)
print(txt)
with open(localfile.name,'w',encoding='utf-8') as f:
f.write(txt)
else:
msgbox.showinfo(message=('读取文件异常'))
def on_exit():
root.destroy()
root =Tk()
root.title("菜单测试")
root.geometry('400x200')
text =Text(root, height=12, width=60,
foreground='darkgray',
font=('微软雅黑',12),
spacing2=8,# 设置行间距
spacing3=12)# 设置段间距
text.pack(fill=BOTH,expand=Y)
st ='Tkinter 为菜单提供了 Menu 类,该类既可代表菜单条,也可代表菜单,还可代表上下文菜单(右键菜单)。简单来说,Menu 类就可以搞定所有菜单相关内容。\n'
text.insert(END, st)
scroll =Scrollbar(text, command=text.yview)
scroll.pack(side=RIGHT, fill=Y)
# 设置text2的纵向滚动影响scroll滚动条
text.configure(yscrollcommand=scroll.set)
text.configure(state=NORMAL)
menubar =Menu(root)
root['menu']= menubar
file_menu =Menu(menubar, tearoff=0)
menubar.add_cascade(label='文件', menu=file_menu)
lang_menu =Menu(menubar, tearoff=0)
menubar.add_cascade(label='格式', menu=lang_menu)
file_menu.add_command(label="新建", command=on_new)
file_menu.add_command(label="打开", command=on_open)
file_menu.add_command(label="保存", command=on_save)
file_menu.add_separator()
file_menu.add_command(label="退出", command=on_exit)
lang_menu.add_command(label="字体", command = None)
lang_menu.add_command(label="颜色", command = None)
def popup(event):
# 在指定位置显示菜单
popup_menu.post(event.x_root, event.y_root)
def choose(x):
# 如果用户选择修改字体大小的子菜单项
if x in my_items[0].keys():
# 改变字体大小
text['font'] = ('微软雅黑', my_items[0][x])
# 如果用户选择修改颜色的子菜单项
if x in my_items[1].keys():
# 改变颜色
text['foreground'] = my_items[1][x]
def handlerAdaptor(fun, **kwds):
return lambda fun=fun, kwds=kwds: fun(**kwds)
text.bind('<Button-3>', popup)
popup_menu = Menu(text, tearoff=0)
my_items = (OrderedDict([('超大', 16), ('大', 14), ('中', 12),
('小', 10), ('超小', 8)]),
OrderedDict([('红色', 'red'), ('绿色', 'green'), ('蓝色', 'blue')]))
i = 0
for k in ['字体大小', '颜色']:
m = Menu(popup_menu, tearoff=0)
popup_menu.add_cascade(label=k, menu=m)
# 遍历OrderedDict的key(默认就是遍历key)
for im in my_items[i]:
m.add_command(label=im, command=handlerAdaptor(choose, x=im))
i += 1
root.mainloop()
欢迎关注我的微信公众号(俊哥随笔),感谢各位的支持!