2018-6-14
5.3.5 偏函数应用示例
from functools import partial as pto
from tkinter import Tk, Button, X
#from tkinter import messagebox
from tkinter.messagebox import showinfo, showwarning, showerror
WARN = 'warn'
CRIT = 'crit'
REGU = 'regu'
SIGN = {
'do not enter': CRIT,
'railroad crossing': WARN,
'55\nspeed limit': REGU,
'wrong way': CRIT,
'merging traffic': WARN,
'one way': REGU
}
critCB = lambda: showerror('ERROR', 'Error Button Pressed!')
warnCB = lambda: showwarning('Warning', 'Warning Button Pressed!')
infoCB = lambda: showinfo('Info', 'Info Button Pressed!')
top = Tk()
top.title('Road Signs')
Button(top, text='Quit',command=top.quit,bg='red',fg='white').pack()
MYBotton = pto(Button, top) #偏函数(固定top参数,其他参数可变,与Button相似)
CritButton = pto(MYBotton,command=critCB,bg='white', fg='red')
WarnButton = pto(MYBotton,command=warnCB,bg='goldenrod1')
ReguButton = pto(MYBotton,command =infoCB,bg='white')
for eachSign in SIGN:
signtype = SIGN[eachSign]
cmd = '%sButton(text=%r%s).pack(fill=X,expand=True)' \
%(signtype.title(), eachSign,'.upper()' if signtype==CRIT else '.title()')
eval(cmd)
top.mainloop()
**********************************************************************************************************
部分代码注释:
1、由于使用python3.6 所以,以前2.5版本的tkMessageBox的导入改为:
from tkinter.messagebox import showinfo, showwarning, showerror
2、偏函数使用MYButton=pto(Button,top)将Button(top,...)中的top参数固定下来,同时不影响其他参数的配置。
3、cmd语句中,格式化输出%r和%s分别表示将所有内容转换成字符串和将内容以字符串形式输出。%r在打印时能够重现其代表的对象:
4、eval(cmd)命令:实现了字符串向list,dict,tuple三种类型的转换,而str()函数刚好相反:实现其他三种类型数据向字符串的转换。
5.3.6 中级tkinter实例
listdir()的复现。
from time import sleep
import os
from tkinter import *
class Dirlist(object):
def __init__(self, initdir=None):
self.top = Tk()
self.label = Label(self.top,text='Directory Lister v1.1')
self.label.pack() # 创建第一个Label控件
self.cwd=StringVar(self.top) # 声明cwd变量,保存当前所在目录名
self.dirl = Label(self.top, fg='blue',font=('Helvetica',12,'bold'))
self.dirl.pack() # 创建了另一个Label控件
# 定义了GUI应用的核心部分Listbox控件dirs,该空间包含了要列出的目录的文件列表。Scrollbar可以让用户在文件数超过Listbox大小时能够移动列表。上诉两个控件都包含在Frame控件中,通过使用Listbox的bind方法,Listbox的列表项可以与回调函数setDirAndGo连接起来。
self.dirfm = Frame(self.top)self.dirsb = Scrollbar(self.dirfm)
self.dirsb.pack(side=RIGHT, fill=Y)
self.dirs= Listbox(self.dirfm, height=15, width=50, \
yscrollcommand=self.dirsb.set)
self.dirs.bind('<Double-1>',self.setDirAndGo)
self.dirsb.config(command=self.dirs.yview)
self.dirs.pack(side=LEFT,fill=BOTH)
self.dirfm.pack()
# 创建了一个文本框,并增加了回车键的绑定,同时,双击条目也可以进行更新文件列表
self.dirn = Entry(self.top, width = 50,textvariable=self.cwd)
self.dirn.bind('<Return>',self.doLS)
self.dirn.pack()
# 定义了一个按钮的框架,放置三个按钮(clear,ls,quit),每个按钮按下时都有自己的配置和回调函数
self.bfm = Frame(self.top)
self.clr = Button(self.bfm, text='Clear',
command=self.clrDir,
activeforeground='white',
activebackground='blue')
self.ls = Button(self.bfm,
text='List Directory',
command=self.doLS,
activeforeground='white',
activebackground='blue')
self.quit = Button(self.bfm,
text='Quit',
command=self.top.quit,
activeforeground='white',
activebackground='red')
self.clr.pack(side=LEFT)
self.ls.pack(side=LEFT)
self.quit.pack(side=LEFT)
self.bfm.pack()
# 构造函数的最后一步分初始化程序,并以当前工作目录作为起始点。
if initdir:
self.cwd.set(os.curdir)
self.doLS()
#clrDir方法可以清空Tk字符串变量cwd(包括当前活动目录)。当发生错误时可以帮助我们回到之前的目录。
回调函数中变量ev的默认值是None,任何像这样的值都是由窗口系统传入的。
def clrDir(self, ev=None):self.cwd.set('')
# 设置要遍历的目录,调用doLS()实现遍历目录的行为
def setDirAndGo(self, ev=None):
self.last = self.cwd.get()
self.dirs.config(selectbackground='red')
check = self.dirs.get(self.dirs.curselection())
if not check:
check = os.curdir
self.cwd.set(check)
self.doLS()
# 整个GUI最关键的部分,他会进行所有的安全检查
def doLS(self,ev=None):
error=''
tdir=self.cwd.get()
if not tdir: tdir=os.curdir
if not os.path.exists(tdir):
errortdir+': no such file'
elif not os.path.isdir(tdir):
error = tdir + ': not a directory'
if error:
self.cwd.set(error)
self.top.update()
sleep(2)
if not (hasattr(self, 'last')\
and self.last):
self.last = os.curdor
self.cwd.set(self.last)
self.dirs.config(selectbackground='LightSkyBlue')
self.top.update()
return
self.cwd.set(\
'FETCHING DIRECTORY CONTENTS...')
self.top.update()
dirlist = os.listdir(tdir)
dirlist.sort()
os.chdir(tdir)
self.dirl.config(text=os.getcwd())
self.dirs.delete(0,END)
self.dirs.insert(END, os.curdir)
self.dirs.insert(END, os.pardir)
for eachFile in dirlist:
self.dirs.insert(END, eachFile)
self.cwd.set(os.curdir)
self.dirs.config(\
selectbackground='LightSkyBlue')
def main():
d = Dirlist(os.curdir)
mainloop()
if __name__=='__main__':
main()