Python核心编程
第五章总结
- GUI模型
- 窗口与控件
顶层的根窗口对象包含组成GUI应用的所有小窗口对象,称为控件。
top = tkinter.Tk()
tkinter.Tk()返回一个根窗口,一个GUI应用可以有很多个顶层窗口,而只能有一个根窗口。
- 事件驱动程序
GUI类似于C/S模型,先加载各种组件和窗口,然后进入主循环,等待事件驱动,然后回调函数。
- 控件
- Label控件
label = Label(master,optional)master为父容器,optional为可选参数。用于包含文本或图像。
import tkinter
top = tkinter.Tk()
label = tkinter.Label(top, text = 'Hello World')
label.pack()
tkinter.mainloop()
mainloop()为主循环,pack()为布局管理。
- Button
与Label类似,但是提供更多的功能,如鼠标悬浮,按下,释放以及键盘活动和事件等。
import tkinter
top = tkinter.Tk()
button = tkinter.Button(top, text = 'Hello World', command = top.quit)
button.pack()
tkinter.mainloop()
command为所绑定的事件,当点击完成后。
- Scale
线性滑块控件,根据已设定的初始值和终止值,给出当前设定的精确值。
from tkinter import *
top = Tk()
top.geometry('250x150')
def resize(ev = None):
label.config(font = 'Helvetica -%d bold' % scale.get())
label = Label(top, text = 'Hello World', font = 'Helvetica 12 bold')
label.pack(fill = Y, 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()
orient指明为垂直还是水平
- 一个综合例子
from functools import partial as pto
from tkinter import Tk,Button,X
from tkinter.messagebox 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!') #showerror向用户显示错误信息,第一个参数指明那种错误,第二个错误为需显示的信息
warnCB = lambda:showwarning('Warning','Warning Button Pressed!')
infoCB = lambda:showinfo('Info','Info Button Pressed!')
top = Tk()
top.title('Road Signs')
#指明top的标题,第一个字母大写,其余小写。
Button(top, text = 'QUIT', command = top.quit, bg = 'red', fg = 'white').pack()
#fg即foreground
MyButton = pto(Button, top)
#partial()函数先冻结给定的参数,当所有的参数都给出的时候或者被调用的时候执行,第一个参数为冻结的函数名,后面为给出的参数值。
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()
第二个例子:
import os
from time import sleep
from tkinter import *
class DirList(object):
def __init__(self, initdir = None):
self.top = Tk()
self.lable = Label(self.top, text = 'Directory Lister v1.1')
self.lable.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) #创建滚动条,yuListbox合用。
self.dirsb.pack(side = RIGHT, fill = Y)
self.dirs = Listbox(self.dirfm, height = 15, width = 50, yscrollcommand = self.dirsb.set) #创建列表框,用于显示一个选择列表
self.dirs.bind('<Double-l>', self.setDirAndGo) #bind用于绑定事件
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) #Entry(输入框)组件通常用于获取用户的输入文本。
#Entry 组件仅允许用于输入一行文本,如果用于输入的字符串长度比该组件可显示空间更长,那内容将被滚动
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')
#activeforeground为未点击的颜色,activebackground为点击时的颜色
self.ls = Button(self.bfm, text = 'List Directory', command = self.doLS, activeforeground = 'white', activebackground = 'red')
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 + ': 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.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) #os.curdir返回执行python文件的文件夹路径
mainloop()
if __name__ == '__main__':
main()
- Tk接口扩展Tix
tix有一些tk没有的控件,如Control,Control由一个文本控件和一组靠近的箭头按钮组成,文本控件中的值可以被附近的一组箭头按钮控制:
ct = Control(top, label = 'Number:', integer = True, max = 12, min = 2, value = 2, step = 2)
ComboBox由一个文本控件和一个下拉选项菜单组成,列表中当前选定的条目会显示在文本控件中。
cb = ComboBox(top, label = 'Type:', editable = True)
for animal in ('dog', 'cat', 'hamster', 'python'):
cb.insert(END, animal)
- 其余的库
PMW
wxWidgets
wxPython
GTK+
PyGTK
ttk