菜单Menu设计的基本概念
窗口中一般有菜单设计,菜单是一种下拉式窗体,在这种窗体中可以设计菜单列表。建立
菜单的方法是Menu(),它的语法格式如下。
Menu(父对象,options,···)
Menu()方法的第一个参数是父对象,表示这个菜单将建立在哪一个父对象内。下列是Menu()
方法内其他常用的options参数。
(1)activebackground:当光标移至此菜单列表上时的背景色彩。
(2)activeborderwidth:当被鼠标选取时它的外边框厚度,默认是1.
(3)activeforeground:当光标移至菜单列表上时的前景色彩。
(4)bd:所有菜单列表的外边框厚度,默认是1。
(5)bg:菜单列表未被选取时的背景色彩。
(6)cursor:当菜单分离时,鼠标光标在列表时的外观。
(7)disabledforeground:菜单列表是DISABLED时的颜色。
(8)font:菜单列表文字的字形。
(9)fg:菜单列表未被选取时的前景色彩。
(10)image:菜单的图标。
(11)tearoff:菜单上方的分隔线,这是一个虚线线条,有分隔线时tearoff值为True或1,此时
菜单列表从位置1开始防止,同时可以让菜单分离,分离方式是开启菜单后单击分隔线。如果将
tearoff设为False或0时,此时不会显示分隔线,也就是菜单无法分离,但是菜单列表将从位置0
开始存放。
下列是其他相关的方法。
(1)add_cascade():建立分层菜单,同时让此子功能列表与父菜单建立链接。
(2)add_command():增加菜单列表。
(3)add_separator():增加菜单列表的分隔线。
样例:建立最上层的菜单列表,单击"Hello!"会出现"欢迎使用菜单"的对话框,单击"Exit!"
则程序结束。
from tkinter import *
from tkinter import messagebox
def hello():
messagebox.showinfo("Hello","欢迎使用菜单")
root=Tk()
root.title("ch16_1")
root.geometry("300x180")
menubar=Menu(root)
menubar.add_command(label="Hello",command=hello)
menubar.add_command(label="Exit",command=root.destroy)
root.config(menu=menubar)
root.mainloop()
上述的设计理念是menubar=Menu(root)线建立menubar对象,然后menubar.add_command(label="Hello",command=hello)
和menubar.add_command(label="Exit",command=root.destroy)分别将Hello!和Exit!命令
列表建立在menubar上。
上述程序虽然可以执行,但这并不是一个很正规的菜单设计方式,正规的菜单是在最上方先建立
菜单类别,然后才在各菜单类别内建立相关子菜单列表,这些子菜单列表是用下拉式窗体显示。
样例2:建立一个File菜单,然后在此菜单内建立下拉式列表命令:
from tkinter import *
from tkinter import messagebox
def newFile():
messagebox.showinfo("New File","新建文档")
root=Tk()
root.title("ch16_2")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar)
menubar.add_cascade(label="File",menu=filemenu)
filemenu.add_command(label="New File",command=newFile)
filemenu.add_command(label="Exit",command=root.destroy)
root.config(menu=menubar)
root.mainloop()
tearoff参数
tearoff参数的默认值是1,至于其他细节可以参考该部分的说明,由于这是默认值,所以若是
开启菜单时可以看到"tearoff"=1参数产生的虚线分隔线。
若单击这个虚线,可以让这个下拉菜单分离。
样例:建立菜单时设置"tearoff=False",隐藏虚线。
from tkinter import *
from tkinter import messagebox
def newFile():
messagebox.showinfo("New File","新建文档")
root=Tk()
root.title("ch16_2")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar,tearoff=False)
menubar.add_cascade(label="File",menu=filemenu)
filemenu.add_command(label="New File",command=newFile)
filemenu.add_command(label="Exit",command=root.destroy)
root.config(menu=menubar)
root.mainloop()
菜单列表间加上分隔线
在建立下拉菜单列表时,如果列表项目有很多,可以适当地使用add_separator()方法在
菜单列表内加上分隔线。
样例:在File菜单内建立5格指令列表,同时适时地在指令列表间建立分隔线。
from tkinter import *
from tkinter import messagebox
def newFile():
messagebox.showinfo("New File","新建文档")
def openFile():
messagebox.showinfo("New File","打开文档")
def saveFile():
messagebox.showinfo("New File","保存文档")
def saveAsFile():
messagebox.showinfo("New File","另存为")
root=Tk()
root.title("ch16_4")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar)
menubar.add_cascade(label="File",menu=filemenu)
filemenu.add_command(label="New File",command=openFile)
filemenu.add_command(label="Open File",command=openFile)
filemenu.add_separator()
filemenu.add_command(label="Save",command=saveFile)
filemenu.add_command(label="Save As",command=saveAsFile)
filemenu.add_separator()
filemenu.add_command(label="Exit",command=root.destroy)
root.config(menu=menubar)
root.mainloop()
建立多个菜单的应用
一个实用的窗口应用程序在最上层menubar中应该会有多组菜单类别。
样例:增加Help菜单,在这个菜单内增加About me命令列表。
from tkinter import *
from tkinter import messagebox
def newFile():
messagebox.showinfo("New File","新建文档")
def openFile():
messagebox.showinfo("New File","打开文档")
def saveFile():
messagebox.showinfo("New File","保存文档")
def saveAsFile():
messagebox.showinfo("New File","另存为")
def aboutMe():
messagebox.showinfo("New File","卢振雄")
root=Tk()
root.title("ch16_4")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar)
menubar.add_cascade(label="File",menu=filemenu)
filemenu.add_command(label="New File",command=openFile)
filemenu.add_command(label="Open File",command=openFile)
filemenu.add_separator()
filemenu.add_command(label="Save",command=saveFile)
filemenu.add_command(label="Save As",command=saveAsFile)
filemenu.add_separator()
filemenu.add_command(label="Exit",command=root.destroy)
helpmenu=Menu(menubar)
menubar.add_cascade(label="Help",menu=helpmenu)
helpmenu.add_command(label="Abount me",command=aboutMe)
root.config(menu=menubar)
root.mainloop()
Alt快捷键
快捷键是某个菜单类别或是列表指令的英文字符串内为单一字母增加下划线,然后可以用Alt
键先启动此功能,当菜单显示下划线字母时,可以直接按执行字母键启动该功能。设计方式是
在下列两个方法内增加underline参数。
add_cascade(···,underline=n) #n代表第几个索引字母含下划线
add_command(···,underline=n) #代表第几个索引字母含下划线
add_cascade()的underline是为菜单类别增加字母下划线,add_command()的underline是为
命令列表增加字母下划线,上述索引从0开始计算。当然,在将所选择的字母处理成带有下画线
时,必须适度选择具有代表性的字母,通常会是字符串的第一个字母。例如File菜单可以选择F,
Help菜单可以选择H,等等。有时候会发生字符串的第一个字母与先前的字母重复,例如,Save
的S与Save As的S,这时第二个出现的字符串可以适当选择其他字母。
样例:为菜单类别和列表命令建立快捷键。
from tkinter import *
from tkinter import messagebox
def newFile():
messagebox.showinfo("New File","新建文档")
def openFile():
messagebox.showinfo("New File","打开文档")
def saveFile():
messagebox.showinfo("New File","保存文档")
def saveAsFile():
messagebox.showinfo("New File","另存为")
def aboutMe():
messagebox.showinfo("New File","卢振雄")
root=Tk()
root.title("ch16_6")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar)
menubar.add_cascade(label="File",menu=filemenu,underline=0)
filemenu.add_command(label="New File",command=openFile,underline=0)
filemenu.add_command(label="Open File",command=openFile,underline=0)
filemenu.add_separator()
filemenu.add_command(label="Save",command=saveFile,underline=0)
filemenu.add_command(label="Save As",command=saveAsFile,underline=5)
filemenu.add_separator()
filemenu.add_command(label="Exit",command=root.destroy,underline=0)
helpmenu=Menu(menubar)
menubar.add_cascade(label="Help",menu=helpmenu,underline=0)
helpmenu.add_command(label="Abount me",command=aboutMe,underline=1)
root.config(menu=menubar)
root.mainloop()
首先必须按Alt键启动此功能。
Ctrl+快捷键
在设计菜单列表时也可以在指令右边设计Ctrl+X之类的快捷键,X是代表一个快捷键的英文字母,
要设计这类操作可以借助accelerator参数,然后再使用bind()方法将此快捷键绑定一个callback()
方法。
样例:设计File菜单的New File子菜单,可以按Ctrl+N组合键。
from tkinter import *
from tkinter import messagebox
def newFile():
messagebox.showinfo("New File","新建文档")
root=Tk()
root.title("ch16_7")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar)
menubar.add_cascade(label="File",menu=filemenu,underline=0)
filemenu.add_command(label="New File",command=newFile,accelerator="Ctrl+N")
filemenu.add_separator()
filemenu.add_command(label="Exit",command=root.destroy,underline=0)
root.config(menu=menubar)
root.bind("<Control-N>",lambda event:messagebox.showinfo("New File","新建文档"))
root.mainloop()
由于所绑定事件会回传event事件给callback()方法,所以无法直接调用newFile()方法,因为newFile()
方法没有传递任何参数,碰上这种问题如果凭直觉再建立一个专供此快捷键使用的方法,此例中
使用Lambda表达式处理,以简化整个程序的设计。
建立子菜单
建立菜单时所使用的概念如下。
menubar=Menu(root)
filemenu=Menu(menubar)
menu.add_cascade(label=" File",menu=filemenu)
上述是建立File菜单。所谓的建立子菜单就是在File菜单内另外建立一个子菜单。如果所要
建立的子菜单是Find子菜单,所要建的对象是findmenu,此时可以使用下列命令。
findmenu=Menu(filemenu)
xxx #这是建立子菜单列表
xxx #这是建立子菜单列表
filemenu.add_cascade(label=" Find",menu=findmenu)
样例:在File菜单内建立Find子菜单,这个子菜单内有FindNext和Find Pre命令。
from tkinter import *
from tkinter import messagebox
def findNext():
messagebox.showinfo("Find Next","查找下一个")
def findPre():
messagebox.showinfo("Find Pre","查找下一个")
root=Tk()
root.title("ch16_8")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar)
menubar.add_cascade(label="File",menu=filemenu,underline=0)
findmenu=Menu(filemenu,tearoff=False)
findmenu.add_command(label="Find Next",command=findNext)
findmenu.add_command(label="Find Pre",command=findPre)
filemenu.add_cascade(label="Find",menu=findmenu)
filemenu.add_separator()
filemenu.add_command(label="Exit",command=root.destroy,underline=0)
root.config(menu=menubar)
root.mainloop()
由于在子菜单的设计中一般省略虚线分隔线设计,所以在Menu()方法中增加了tearoff=False
建立弹出式菜单
当使用Windows操作系统时,可以在桌面上单击鼠标右键,此时会弹出一个菜单,这就是
弹出式菜单Popup menu,有人将此菜单称为快捷菜单。
设计这类菜单与先前需在窗口的menubar区建立菜单类别有一些差异,建立好Menu对象后,
可以直接利用此对象建立指令列表,最后再单击鼠标右键操作绑定显示弹出菜单即可。
popupmenu=Menu(root,tearoff=False) #隐藏虚线分隔线
popupmenu.add_command(label=" xx",command=" yy" 建立指令列表
···.
root.bind("<Button-3>",callback) #绑定单击鼠标右键显示弹出菜单)
样例:设计弹出菜单,这个弹出菜单中有两个子菜单,一个是Minimize可以将窗口缩成
图标,另一个是Exit结束程序。
from tkinter import *
from tkinter import messagebox
def minimizeIcon():
root.iconify()
def showPopupMenu(event):
popupmenu.post(event.x_root,event.y_root)
root=Tk()
root.title("ch16_9")
root.geometry("300x180")
popupmenu=Menu(root,tearoff=False)
popupmenu.add_command(label="Minimize",command=minimizeIcon)
popupmenu.add_command(label="Exit",command=root.destroy)
root.bind("<Button-3>",showPopupMenu)
root.mainloop()
iconify()是最小化窗口,post()方法是由popupmenu对像启动,相当于可以在鼠标
光标位置(event.x_root,event.y_root)弹出此菜单。
add_checkbutton()
在设计菜单列表时,也可以将命令用复选框(checkbutton)方式表示,也称为
Check menu button,下面将用程序实例讲解。执行时,在窗口下方可以看到
状态栏,View菜单中的Status其实就是用的复选框命令。
上述工作原理是当Status状态为True时,Status左边可以勾选符号,同时窗口下方
会有状态栏。当Status状态是False时,左边没有勾选符号,同时窗口下方不会有状态栏。
Check menu button的工作原理和Widget对象Checkbutton相同,单击可以切换状态True
或False。
样例:设计当Status为True时可以显示状态栏,当Status为False时可以隐藏状态栏,这个
程序的状态栏是用标签Label方式处理。
from tkinter import *
def status():
if demoStatus.get():
statusLabel.pack(side=BOTTOM,fill=X)
else:
statusLabel.pack_forget()
root=Tk()
root.title("ch16_10")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar,tearoff=False)
menubar.add_cascade(lab="File",menu=filemenu)
filemenu.add_command(label="Exit",command=root.destroy)
viewmenu=Menu(menubar,tearoff=False)
menubar.add_cascade(label="View",menu=viewmenu)
demoStatus=BooleanVar()
demoStatus.set(True)
viewmenu.add_checkbutton(label="Status",command=status,
variable=demoStatus)
root.config(menu=menubar)
statusVar=StringVar()
statusVar.set("显示")
statusLabel=Label(root,textvariable=statusVar,relief="raised")
statusLabel.pack(side=BOTTOM,fill=X)
root.mainloop()
上述程序的重点如下:在View菜单内使用add_checkbutton()创建Check menu button,
此对象名称是Status,同时使用demoStatus布尔变量记录目前状态是True或False,这个
Status对象当有状态改变时执行status()方法。
status()方法中如果目前demoStatus是True,执行statusLabel.pack(side=BOTTOM,fill=X)
包装显示窗口的标签状态栏,相当于显示statusLabel。如果目前demoStatus是False,执行
statusLabel.pack_forget(),这个方法可以隐藏状态标签栏。
建立工具栏Toolbar
在窗口程序设计中,另一个很重要的概念是将常用的命令组成工具栏,放在窗口内以方便用户
随时调用。tkinter模块没有提供Toolbar模块,不过我们可以使用Frame建立工具栏。
样例:这个程序会建立一个File菜单,菜单内有Exit命令。这个程序也建立一个工具栏,在工具栏
内有exitBtn按钮。这个程序不论是执行File菜单的Exit命令或是单击工具栏中的exitBtn按钮,都
可以让程序结束。
from tkinter import *
root=Tk()
root.title("ch16_10")
root.geometry("300x180")
menubar=Menu(root)
filemenu=Menu(menubar,tearoff=False)
menubar.add_cascade(lab="File",menu=filemenu)
filemenu.add_command(label="Exit",command=root.destroy)
toolbar=Frame(root,relief=RAISED,borderwidth=3)
sunGif=PhotoImage(file="sun.gif")
exitBtn=Button(toolbar,image=sunGif,command=root.destroy)
exitBtn.pack(side=LEFT,padx=3,pady=3)
toolbar.pack(side=TOP,fill=X)
root.config(menu=menubar)
root.mainloop()