创建一个GUI程序的五个基本步骤是
1.导入Tkinter模块。 2.创建一个顶层窗口对象,来容纳你的整个GUI程序。 3.在你的顶层窗口对象上创建所有的GUI模块。 4.把这些GUI模块与底层代码相连。 5.进入主事件循环
top = Tkinter.Tk() 便可创建一个顶层窗口,因为Tkingter.Tk()返回的对象有时被称为根窗口,所以也有用root而不是top作为名称的情况
顶层窗口是程序中独立显示的部分。我们可以拥有多个顶层窗口,但只能有一个根窗口。
当我们说创建一个顶层窗口的时候,实际上是需要一个放置所有组件的地方,组件既可以是独立的也可以作为容器存在。通常,组件会有一些相应的行为,例如按钮被按下,或者文本框被写入,这种形式的用户行为被称为事件,而GUI程序对事件所采取的响应动作称为回调。
用户操作可以包括按下(及释放)按钮、移动鼠标、按下RETURN或ENTER键等等,所有的这些从系统角度都被看作事件。GUI程序正是由事件驱动的,整个过程被称作事件驱动处理。
一个事件及其回调的例子是鼠标移动。我们假设鼠标指针停在GUI程序中的某处,如果鼠标被移动到了程序的别处,一定是有什么东西引起了屏幕上指针的移动,从而表现这种位置的转移。系统必须处理这些鼠标移动事件才能实现鼠标在窗口上的移动。一旦你释放了鼠标,就不再会有事件需要处理,相应地,屏幕上一切又恢复平静。
GUI程序的事件驱动特性恰好体现出它的客户端/服务器架构。当你启动一个GUI程序时,它必须执行一些初始化例程来为核心功能的运行做准备,正如启动一个网络服务器时必须先申请一个套接字并把它绑定到一个本地地址上一样。Tk有两个坐标管理器用来协助把组件放在正确的位置上,其中一个是包,即packer,另一个是网格,即Grid。你可以用网格来把GUI组件放在网络坐标系中,Grid将依据GUI中的网络坐标系来生成每个对象。
一但packer决定好你所有组件的尺寸和对齐方式,它将为你在屏幕上放置它们,当所有这些组件,包括顶层窗口,最终显示在你屏幕上时,GUI程序就会进入一个“服务器式”的无限循环,这个无限循环包括等待GUI事件、处理事件、然后返回等待模式。
上述最后一步说明所有组件就绪后立即进入主循环,这正是我们提及的“服务器式”无限循环,对Tinker而言,相应代码如下:
Tkinter.mainloop()
这通常是程序执行的最后一段代码。一旦进入主循环,GUI便从此掌握控制权,所有其他动作都来自回调函数,包括程序退出。当你拉下文件菜单点击“退出”菜单项或直接关闭窗口时,必须要唤起一个回调来结束你的程序。
19.2.3顶层窗口:Tkiner.Tk()
我们前面提到所有的主要组件都建立在顶层窗口对象内,这个对象是由Tkinter中的Tk类创建的,并且是由普通构造器创建的:
>>>import Tkinter
>>>top = Tkinter.Tk()
在这个窗口中,你可以放置独立组件或集成的模块来构建你的GUI。那么,有哪些组件可用呢?
19.2.4Tk组件
组件 | 描述 |
Button | 按钮。类似标签,但提供额外的功能,例如鼠标掠过、按下、释放及键盘操作/时间 |
Canvas | 画布。提供绘图功能(直线、椭圆、多边形、矩形);可以包含图形或位图 |
Checkbutton |
选择按钮。一组方框,可以选择其中的人一个(类似HTML中的checkbox) |
Entry |
文本框。单行文字域,用来收集键盘输入(类似HTML中的text) |
Frame |
框架。包含其他组件的纯容器 |
Label |
标签。用来显示文字或图片 |
Listbox |
列表框。一个选项列表,用户可以从中选择 |
Menu |
菜单。点下菜单按钮后弹出的一个选项列表,用户可以从中选择 |
Menubutton |
菜单按钮。用来包含菜单的组件(有下拉式、层叠式等等) |
Message |
消息框。类似标签,但可以显示多行文本 |
Radiobutton |
单选按钮。一组按钮,其中只有一个可被“按下”(类似HTML的radio) |
Scale |
进度条。线性“滑块”组件,可设定初始值和结束指,会显示当前位置的精确值 |
Scrollbar |
滚动条。请对其支持的组件(文本域、画布、列表框、文本框)提供滚动功能 |
Text |
文本域。多行文字区域,可用来收集(或显示)用户输入的文字(类似HTML中的textarea) |
Toplevel |
顶级。类似框架,但提供一个独立的窗口容器 |
核心笔记:GUI开发从Python的缺省参数机制获益匪浅,因为Tkinter组件有大量的默认动作。除非你熟知自己使用的每一个组件的每一个可用选项,否则最好只设置你关心的参数而把其他的交给系统处理。
19.3Tkinter举例
1 import Tkinter 2 top = Tkinter.Tk() 3 label = Tkinter.Label(top, text='Hello World!') 4 label.pack() 5 Tkinter.mainloop()
19.3.2按钮组件
第二个例子和第一个很相似。但我们这次将创建一个按钮而不是只显示一个文字标签
1 import Tkinter 2 top = Tkinter.Tk() 3 quit = Tkinter.Button(top, text='Hello World!', 4 command=top.quit) 5 quit.pack() 6 Tkinter.mainloop()
19.3.3标签和按钮组件
第三个例子,通过fill参数和expand参数调整QUIT按钮的位置
1 import Tkinter 2 top = Tkinter.Tk() 3 4 hello = Tkinter.Label(top, text='Hello World!') 5 hello.pack() 6 7 quit = Tkinter.Button(top, text='Quit', command=top.quit,bg='red',fg='white') 8 quit.pack(fill=Tkinter.X, expand=1) 9 Tkinter.mainloop()
19.3.4标签、按钮和进度条组件
第四个例子,重点是组件间回调函数的交互(例如resize())。
1 from Tkinter import * 2 3 def resize(ev=None): 4 label.config(font='Helvetica -%d bold' % 5 scale.get()) 6 top = Tk() 7 top.geometry('300x200') 8 9 label = Label(top, text = 'Hello World!', 10 font = 'Helvetica -12 bold') 11 label.pack(fill=Y, expand=1) 12 13 scale = Scale(top, from_=10, to=40, 14 orient=HORIZONTAL, command=resize) 15 scale.set(12) 16 scale.pack(fill=X, expand=1) 17 18 quit = Button(top, text='QUIT', 19 command=top.quit, activeforeground='white', 20 activebackground='red') 21 quit.pack() 22 mainloop()
19.3.5偏函数应用举例
回顾一下GUI函数。
偏函数允许你‘预存’一些函数变量并有效地‘冻结’了这些预定参数,在运行时你获得了所需的其他变量后再把它们解冻出来,用这些最终确定的参数去调用函数。
偏函数不仅可以作用于函数,它对任何’可调用‘的东西都有效,任何有函数接口的对象,比如类、方法、或可调用对象,只要是有括号的。对于有许多待调对象并且许多调用都反复使用相同参数的情况,用偏函数是再合适不过的。
GUI编程有很好的操作环境,因为很有可能你需要GUI组件有某些一致的外观和体验,而这些一致性表现在可以使用相同的参数创建相似的对象。
1 from functools import partial as pto 2 from Tkinter import Tk, Button, X 3 from tkMessageBox import showinfo, showwarning, showerror 4 5 WARN = 'warn' 6 CRIT = 'crit' 7 REGU = 'regu' 8 9 SIGNS = { 10 'do not enter':CRIT, 11 'railroad crossing':WARN, 12 '55 speed limit':REGU, 13 'wrong way':CRIT, 14 'merging traffic':WARN, 15 'one way':REGU, 16 } 17 18 critCB = lambda: showerror('Error', 'Error Button pressed!') 19 warnCB = lambda: showwarning('Warning', 'Warning Button Pressed!') 20 infoCB = lambda: showinfo('Info', 'Info Button Pressed!') 21 22 top = Tk() 23 top.title('Road Signs') 24 Button(top, text='QUIT', command = top.quit, bg='red', fg='white').pack() 25 26 MyButton = pto(Button, top) 27 CritButton = pto(MyButton, command=critCB, bg='blue', fg='red') 28 WarnButton = pto(MyButton, command=warnCB, bg='goldenrod1', fg='red') 29 ReguButton = pto(MyButton, command=infoCB, bg='white') 30 31 for eachSign in SIGNS: 32 signType = SIGNS[eachSign] 33 cmd = '%sButton(text=%r%s).pack(fill=X, expand=True)' % (signType.title(), 34 eachSign, '.upper()' if signType == CRIT else '.title()') 35 eval(cmd) 36 37 top.mainloop()
19.3.6中级TKinter范例
这个例子是一个目录树遍历工具,新增使用了列表框、文本框和滚动条。还有大量回调函数,例如鼠标点击、键盘输入和滚动条操作。