19.1 简介
19.1. 什么是Tcl、Tk和Tkinter
Tkinter是Python的默认GUI库,它基于Tk工具集,后者最初是为工具命令语言Tcl设计的。
19.2 Tkinter与Python编程
19.2.1 Tkinter模块:把Tk引入你的程序
1.导入Tkinter模块
2.创建一个顶层窗口对象,来容纳你的整个GUI程序
3.在你的顶层窗口对象上创建所有的GUI模块(以及功能)
4.把这些GUI模块与顶层程序代码相连接
5.进入主事件循环
19.2.2 GUI程序开发简介
创建一个顶层窗口的时候,我们实际上是指你需要一个放置所有组件的地方。典型的Pyhton语句如下行:
top = Tkinter.Tk()
Tkinter.Tk()返回的对象通常被称作根窗口,正因为如此,有些程序用root来指示它,而非top。
顶层窗口是指哪些在你的程序中独立显示的部分,你可以在GUI程序中创建多个顶层窗口,但它们中只能有一个是根窗口
可以采用完全设计好组件再添加实际功能的开发方式,也可以二者同时进行。组件既可以是独立的也可以作为容器存在。
通常,组件会有一些相应的行为,例如按钮被按下,后者文本框被写入,这种形式的用户行为被称为事件,而GUI程序对事件所采取的相应动作被称为回调。
Tk有两个坐标管理器用来协助把组件放在正确的位置,你将经常用到的一个称为“包”,亦即packer。另一个坐标管理器是网格(Grid)。你可以用来把GUI组件放在网格坐标系中,Grid将依据
GUI中的网格坐标来生成每个对象。
程序执行的最后一段代码:
Tkinter.mainloop()
19.2.3顶层窗口:Tkinter.Tk()
import Tkinter
top = Tkinter.Tk()
19.2.4 Tk组件
Tk目前有15中组件。
例子:
#-*-coding:utf-8-*-
import Tkinter
top=Tkinter.Tk()
label = Tkinter.Label(top,text='Hello World!')
label.pack()
Tkinter.mainloop()
19.3 Tkinter 举例
19.3.1标签组件
19.3.2按钮组件
#-*-coding:utf-8-*-
import Tkinter
top=Tkinter.Tk()
quit = Tkinter.Button(top,text='Hello World!',command=top.quit)
quit.pack()
Tkinter.mainloop()
19.3.3 标签和按钮组件
#-*-coding:utf-8-*-
import Tkinter
top=Tkinter.Tk()
hello = Tkinter.Label(top,text='Hello World!')
hello.pack()
quit = Tkinter.Button(top,text='QUIT',command = top.quit,bg='red',fg='white')
quit.pack(fill=Tkinter.X,expand=1)
Tkinter.mainloop()
19.3.4标签、按钮和进度条组件
例子:增加一个进度条组件,具体来说,这个进度条是用来和标签组件交互的。进度条的滑块被用作控制标签组件文本大小的工具。滑块的位置值越大字体就越大,反之亦然,越小的位置值意味着越小的字体
#-*-coding:utf-8-*-
from Tkinter import *
#回调函数
def resize(ev=None):
label.config(font="Helveti -%d bold" % scale.get())
top = Tk()
#限定尺寸
top.geometry('250x150')
label = Label(top,text='Hello World!',font='Helvetica -12 bold')
label.pack(fill=X,expand=1)
scale = Scale(top,from_=10,to=40,orient=HORIZONTAL,command=resize)
scale.set(12)
scale.pack(fill=X,expand=1)
quit = Button(top,text='QUIT',command=top.quit,activeforeground='white',
activebackground='red')
quit.pack()
mainloop()
19.3.5偏函数应用举例
#-*-coding:utf-8-*-
from functools import partial as pto
from Tkinter import Tk,Button,X
from tkMessageBox import showinfo,showwarning,showerror
WARN ='warn'
CRIT ='crit'
REGU ='regu'
SIGNS = {
'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()
MyButton = pto(Button,top)
CritButton = pto(MyButton,command=critCB,bg='white',fg='red')
WarnButton = pto(MyButton, command=warnCB,bg='goldenrod1')
ReguButton = pto(MyButton,command = infoCB,bg='white')
for eachSign in SIGNS:
signType=SIGNS[eachSign]
cmd = '%sButton(text=%r%s).pack(fill=X,expand=True)' %(
signType.title(),eachSign,'.upper()'if signType ==CRIT else '.title()'
)
eval(cmd)
top.mainloop()
19.3.6中级Tkinter范例
#-*-coding:utf-8-*-
import os
from time import sleep
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()
self.cwd = StringVar(self.top)
self.dirl = Label(self.top,fg='blue',font=('Helvetica',12,'bold'))
self.dirl.pack()
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.dirn=Entry(self.top,width=50,textvariable=self.cwd)
self.dirn.bind('<Return>,self.doLS')
self.dirn.pack()
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 = 'green')
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()
def clrDir(self,ev=None):
self.cwd.set('')
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()
def doLS(self,ev=None):
error = ''
tdir=self.cwd.get()
if not tdir: tdir = os.curdir
if not os.path.exists(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.curdir
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()
19.4 其他GUI简介
19.5相关模块和其他GUI
19.6练习
19-1 客户端/服务器架构。请描述窗口服务器的角色和窗口客户端的角色。
窗口服务器运行在一个有显示的设备上,显示GUI程序
窗口客户端指GUI程序
19-2 面向对象编程,请描述子窗口与父窗口的关系。
如果一个组件”包含“其他组件,它就被认为是这些组件的父组件,相应的,如果一个组件被”包含“在其他组件中,它就被认为是父组件的孩子,父组件是直接包围其外的那个容器组件。