python GUI编程

GUI:Graphical User Interface图形用户界面

1  简介

Tkinter是Python的默认GUI库, 基于Tk工具包,该工具包最初是为工具命令语言(Tool Command Language,Tcl)设计的。Tk普及后,被移植到很多其他的脚本语言中,包括Perl(Perl/Tk)、Ruby(Ruby/Tk)和Python(Tkinter)。

Python3模块为tkinter。

2  Tkinter和python编程

2.1  添加Tk到应用中

让GUI 程序启动和运行起来需要以下5 个主要步骤:

1.导入tkinter模块。

2.创建一个顶层窗口对象,用于容纳整个GUI应用。

3.在顶层窗口对象之上(或者“其中”)构建所有的GUI 组件(及其功能)。

4.通过底层的应用代码将这些GUI组件连接起来。

5.进入主事件循环

2.2  GUI编程介绍

1、窗口与控件

在GUI编程中,顶层的根窗口对象包含组成GUI应用的所有小窗口对象。它们可能是文字标签、按钮、列表框等。这些独立的GUI组件称为控件。所以当我们说创建一个顶层窗口时,只是表示需要一个地方来摆放所有的控件。

tkinter.Tk()返回的对象通常称为根窗口

2、事件驱动处理

一个GUI应用从开始到结束就是通过整套事件体系来驱动的,事件可以包括按钮按下(及释放)、鼠标移动、敲击回车键等。

当布局管理器排列好所有控件后,GUI应用进入其类似服务器的无限循环。这个循环会一直运行,直到出现GUI事件,进行处理,然后再等待更多的事件去处理

3、布局管理

Tk有3 种布局管理器:

1)  Placer:提供控件的大小和摆放位置,然后管理器就会将其摆放好

2)  Packer:主要使用,把控件填充到正确的位置,然后对于之后的每个控件,会去寻找剩余的空间进行填充

3)  Grid:基于网格坐标,使用Grid来指定GUI控件的放置

2.3  Tk控件

控件

描述

Button

与Label类似,但提供额外的功能,如鼠标悬浮、按下、释放以及键盘活动/事件

Canvas

提供绘制形状的功能(线段、椭圆、多边形、矩形),可以包含图像或位图

Checkbutton

一组选框,可以勾选其中的任意个(与HTML的checkbox输入类似)

Entry

单行文本框,用于收集键盘输入(与HTML的文本输入类似)

Frame

包含其他控件的纯容器

Label

用于包含文本或图像

LabelFrame

标签和框架的组合,拥有额外的标签属性

Listbox

给用户显示一个选项列表来进行选择

Menu

按下Menubutton后弹出的选项列表,用户可以从中选择

Menubutton

用于包含菜单(下拉、级联等)

Message

消息。与Label类似,不过可以显示成多行

PanedWindow

一个可以控制其他控件在其中摆放的容器控件

Radiobutton

一组按钮,其中只有一个可以“按下”(与HTML的radio输入类似)

Scale

线性“滑块”控件,根据已设定的起始值和终止值,给出当前设定的精确值

Scrollbar

为Text、Canvas、Listbox、Enter等支持的控件提供滚动功能

Spinbox

Entry 和Button 的组合,允许对值进行调整

Text

多行文本框,用于收集(或显示)用户输入的文本(与HTML的textarea类似)

Toplevel

与Frame类似,不过它提供了一个单独的窗口容器

2.4  Tkinter示例

2.4.1  Label控件

1 import tkinter
2 
3 top = tkinter.Tk()       #创建了一个顶层窗口
4 
5 label = tkinter.Label(top,text='Hello World!')   #Label控件,包含Hello World字符串
6 label.pack()            #使用Packer来管理和显示控件
7 tkinter.mainloop()      #运行GUI应用,tkinter.mainloop()可以让应用进入无限主循环中

运行结果:

2.4.2  Button控件

1 import tkinter
2 
3 top = tkinter.Tk()       #创建了一个顶层窗口
4 
5 #Button控件,当按钮被按下(并且释放)后,整个程序就会退出
6 label = tkinter.Button(top,text='quit',command=top.quit,bg='red',fg='green')  
7 label.pack()            #使用Packer来管理和显示控件
8 tkinter.mainloop()      #运行GUI应用,tkinter.mainloop()可以让应用进入无限主循环中

运行结果:

2.4.3  偏函数应用

1)偏函数

functools.partial偏函数的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单

2)偏函数应用示例

 1 from functools import partial as pto   #偏函数
 2 from tkinter import Tk,Button,X
 3 from tkinter.messagebox 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\nspeed limit':REGU,
13     'wrong way':CRIT,
14     'merging traffic':WARN,
15     'one way':REGU
16 }
17 
18 ##各种标志类型按钮的回调函数##
19 critCB = lambda:showerror('Error','Error Button Pressed!')
20 warnCB = lambda:showwarning('Warning','Warning Button Pressed!')
21 infoCB = lambda:showinfo('Info','Info Button Pressed!')
22 
23 top = Tk()     #顶层窗口
24 top.title('Road Signs')    #设置标题
25 Button(top,text='QUIT',command=top.quit,bg='red',fg='white').pack()   #设置QUIT按钮,使用Packer来管理和显示控件
26 
27 ##偏函数用法##
28 #模板化Button类和根窗口top;调用MyButton时,就会调用Button类(tkinter.Button()创建一个按钮),并将top作为它的第一个参数
29 MyButton = pto(Button,top)  
30 #模板化每种标志类型,创建单独的按钮类型
31 CritButton = pto(MyButton,command=critCB,bg='white',fg='red')
32 WarnButton = pto(MyButton,command=warnCB,bg='goldenrod1')
33 ReguButton = pto(MyButton,command=infoCB,bg='white')
34 
35 for eachSign in SIGNS:
36     signType = SIGNS[eachSign]
37     '''
38     expand置1 使能fill属性
39     expand置0 关闭fill属性
40     fill=X 当GUI窗体大小发生变化时,widget在X方向跟随GUI窗体变化
41     fill=Y 当GUI窗体大小发生变化时,widget在Y方向跟随GUI窗体变化
42     fill=BOTH 当GUI窗体大小发生变化时,widget在X、Y两方向跟随GUI窗体变化 
43     '''
44     # title() 方法返回"标题化"的字符串,就是说所有单词都是以大写开始,其余字母均为小写
45     cmd = '%sButton(text=%r%s).pack(fill=X,expand=True)' % (signType.title(),eachSign,'.upper()' if signType == CRIT else '.title()')
46     #eval()将字符串str当成有效的表达式来求值并返回计算结果
47     eval(cmd)
48 
49 top.mainloop()

运行结果:

2.4.4  Tkinter示例(目录树遍历)

  1 import os
  2 from time import sleep
  3 from tkinter import *
  4 
  5 class DirList(object):
  6     def __init__(self,initdir=None):
  7         self.top = Tk()   #顶层窗口
  8         self.label = Label(self.top,text='Directory Lister V1.1') #Label控件,包含字符串
  9         self.label.pack()  #使用Packer来管理和显示控件
 10 
 11         self.cwd = StringVar(self.top)   #用于保存当前所在的目录名
 12 
 13         #用于显示当前的目录名
 14         self.dirl = Label(self.top,fg='blue',font=('Helvetica',12,'bold'))
 15         self.dirl.pack()
 16 
 17         #Scrollbar与Listbox控件包含在Frame控件中
 18         self.dirfm = Frame(self.top)
 19         self.dirsb = Scrollbar(self.dirfm)  #文件树超过Listbox的大小能够移动列表
 20         #side按扭停靠在窗口的哪个位置,fill填充(x:水平方向,y:竖直方向,both:水平和竖直方向,none:不填充)
 21         self.dirsb.pack(side=RIGHT,fill=Y)  
 22         #列出目录的文件列表,yscrollcommand创建一个垂直滚动条 
 23         self.dirs = Listbox(self.dirfm,height=15,width=50,yscrollcommand=self.dirsb.set) 
 24         #绑定操作,这意味着将一个回调函数与按键、鼠标操作或者其他的一些事件连接起来,这里当双击任意条目时,会调用setDirAndGo函数
 25         self.dirs.bind('<Double-1>',self.setDirAndGo)
 26         self.dirs.pack(side=LEFT,fill=BOTH)
 27         self.dirfm.pack()
 28 
 29         #创建一个文本框,可以输入遍历的目录名
 30         #Entry是tkinter 用来接收字符串等输入的控件
 31         self.dirn = Entry(self.top,width=50,textvariable=self.cwd)
 32         #回车绑定
 33         self.dirn.bind('<Return>',self.doLS)
 34         self.dirn.pack()
 35 
 36         #定义一个按钮框架
 37         self.bfm = Frame(self.top)
 38         self.clr = Button(self.bfm,text='Clear',command=self.clrDir,activeforeground='white',activebackground='blue')
 39         self.ls = Button(self.bfm,text='List Directory',command=self.doLS,activeforeground='white',activebackground='green')
 40         self.quit = Button(self.bfm,text='Quit',command=self.top.quit,activeforeground='white',activebackground='red')
 41         self.clr.pack(side=LEFT)
 42         self.ls.pack(side=LEFT)
 43         self.quit.pack(side=LEFT)
 44         self.bfm.pack()
 45 
 46         #初始化GUI程序,以当前工作目录作为起始点
 47         if initdir:
 48             self.cwd.set(os.curdir) #os.curdir:返回当前目录('.')
 49             self.doLS()
 50 
 51     '''
 52     清空TK字符串变量cwd,当发生错误时可以回到之前的目录
 53     ev默认为None,值是有窗口系统传入的,回调函数中可能会用到,也可能用不到
 54     '''
 55     def clrDir(self,ev=None):
 56         self.cwd.set('')
 57 
 58     #设置要遍历的目录函数
 59     def setDirAndGo(self,ev=None):
 60         self.last = self.cwd.get()
 61         self.dirs.config(selectbackground='red') #双击时,设置背景色为红色
 62         check = self.dirs.get(self.dirs.curselection()) #curselection()返回当前选中项的索引,get()返回制定索引的项值
 63         if not check:
 64             check = os.curdir
 65         self.cwd.set(check)
 66         self.doLS()
 67 
 68     def doLS(self,ev=None):
 69         error=''
 70         tdir = self.cwd.get()
 71         if not tdir:tdir = os.curdir #os.curdir:返回当前目录('.')
 72 
 73         if not os.path.exists(tdir): #判断文件是否存在
 74             error = tdir + ':no such file'
 75         elif not os.path.isdir(tdir): #判断是否是目录
 76             error = tdir + ':not a directory'
 77 
 78         if error:
 79             self.cwd.set(error)
 80             self.top.update()
 81             sleep(2)
 82             if not (hasattr(self,'last') and self.last):#hasattr判断一个对象里面是否有last属性或者last方法
 83                 self.last = os.curdir
 84             self.cwd.set(self.last)
 85             self.dirs.config(selectbackground='LightSkyBlue')
 86             self.top.update()
 87             return
 88 
 89         self.cwd.set('FETCHING DIRECTORY CONTENTS...')
 90         self.top.update()
 91         dirlist = os.listdir(tdir) #获取实际文件列表
 92         dirlist.sort()
 93         os.chdir(tdir)  #改变当前工作目录到指定的路径
 94 
 95         self.dirl.config(text=os.getcwd())  #os.getcwd()返回当前进程的工作目录
 96         self.dirs.delete(0,END)  #删除所有元素
 97         #insert()导入listbox中
 98         self.dirs.insert(END,os.curdir)  
 99         self.dirs.insert(END,os.pardir)  #os.pardir上级目录
100         for eachFile in dirlist:
101             self.dirs.insert(END,eachFile)
102         self.cwd.set(os.curdir)
103         self.dirs.config(selectbackground='LightSkyBlue')
104 
105 def main():
106     DirList(os.curdir) #os.curdir:返回当前目录('.')
107     mainloop()
108 
109 if __name__=='__main__':
110     main()

运行结果:

 

3  其他GUI

1)  Tix(Tk接口扩展)

2)  Pmw(Python MegaWidgets Tkinter扩展)

3)  wxPython(wxWidgets的Python版本)

4)  PyGTK(GTK+的python版本)

猜你喜欢

转载自www.cnblogs.com/longBlogs/p/9904815.html