pytho GUI编程之Tkinter

摘录 python核心编程spython

GUI(Graphical User Interface)图形用户界面。编程

Tcl、Tk和Tkinterpython3.x

Tkinter是python的默认GUI库。它基于Tk工具包,该工具包最初是为工具命令语言(Tcl)设计的。Tk普及后,被移植到不少其余的脚本语言中,包括Perl(Perl/Tk)、Ruby(Ruby/Tk)和Python(Tkinter)。服务器

安装和使用Tkinter网络

Tkinter在系统中不是默认必须安装的,能够经过在python解释器中尝试导入Tkinter模块(在Python3中重命名为tkinter)来检查Tkinter是否可用。这里我测试的环境是Python3.6,这里没有发生错误:架构

>>> import tkinter
>>>

若是失败了的话,就须要从新编译Python解释器以使用tkinter了。框架

tkinter和Python编程函数

让GUI程序启动和运行起来须要如下5个步骤:工具

  1. 导入tkinter模块
  2. 建立一个顶层窗口对象,用于容纳整个GUI应用
  3. 在顶层窗口对象之上构建全部的GUI组件及其功能
  4. 经过底层的应用代码将这些GUI组件链接起来
  5. 进入主事件循环

窗口和控件oop

在GUI编程中,顶层的根窗口对象包含组成GUI应用的全部的小窗口对象。它们多是文字标签、按钮、列表框等。这些独立的GUI组件称为控件(widget)。因此当咱们说建立一个顶层窗口时,只是表示须要一个地方来摆放全部的控件。通常写成:

top = tkinter.Tk() #或者当采用‘from tkinter import *’ 时,也可直接写成 Tk()

tkinter.Tk()返回的对象一般称为根窗口,这也是一些应用使用root而不是top来指代它的缘由。

顶层窗口是那些在应用中独立显示的部分。GUI程序中能够有多个顶层窗口,可是只有一个是根窗口。

控件能够独立存在,也能够做为容器存在。若是一个控件包含其余控件,就能够将其认为是那些控件的父控件。相应的,若是一个控件被其余控件包含,则称这个控件是那个控件的子控件。

事件驱动处理

一般,控件有一些相关的行为,好比按下按钮、将文本写入文本框、敲击回车等。这些行为称为事件。而GUI对这类事件的响应称为回调。

一个GUI程序从开始到结束就是经过整套事件体系来驱动的,这种方式称为事件驱动处理。

好比,最简单的鼠标移动。假设鼠标正停在GUI应用顶层窗口某处,将鼠标移动到另外一部分,鼠标移动的行为会被复制到屏幕的光标上,因而看起来像是你的手在移动。系统必须处理的这些鼠标移动事件能够绘制窗口上的指针移动。当释放鼠标时,再也不有事件须要处理,此时屏幕会从新恢复闲置的状态。

事件驱动的GUI处理本质上很是适合客户端/服务器架构。当启动一个GUI应用时,须要一些启动步骤来准备核心部分的执行,就像网络服务器启动时必须先分配套接字并将其绑定到本地地址上同样。GUI应用必须先建立全部的GUI组件,而后将他们绘制在屏幕上。这是布局管理器的职责所在。当布局管理器排列好全部空间后,GUI应用进入相似服务器的无限循环。这个循环一直运行,直到出现GUI事件,进行处理。

布局管理器

Tk有3种布局管理器来帮助控件进行定位。最原始的一种称为Placer。他的作法很是直接:你提供控件的大小和位置,而后交给布局管理器。这就存在很大的问题,你必须对全部控件进行这些操做,开发者很大负担。

第二种布局管理器,Packer,也是咱们主要是用的。它会把控件填充到正确的位置(即指定的父控件中),而后对于以后的每一个控件,回去寻找剩余的空间进行填充。这个处理很像是旅行时往行李箱中填充行李的过程。

第三种布局管理器是Grid。你能够基于网格坐标,使用Grid来指定GUI空间的放置。Grid会在它们的网格位置上渲染GUI应用中的每一个对象。

本次学习中咱们使用Packer。一旦Packer肯定好全部控件的大小和对齐方式,它就会在屏幕上将其位置放置稳当。

当全部的控件摆放好后,可让应用进入无限主循环中,代码以下:Tkinter.mainloop()

通常来讲,这是程序运行的最后一段代码。当进入主循环后,GUI就从这里开始接管程序的执行,全部其余行为都会经过回调来处理,包括退出应用。

顶层窗口:Tkinter.Tk()

以前提到的全部主要控件都是构建在顶层窗口对象之上的,该对象在tkinter中使用Tk类进行建立:

>>> import tkinter
>>> top = tkinter.Tk()

在这个窗口中,能够放置独立的控件,也能够将多个组件拼凑在一块儿构成GUI程序。下面开始介绍Tk控件

Tk控件

下面介绍了18种Tk控件(更多或者更详细的资料参考Python主站上的Tkinter主题页):

控件 描述
Button 于Label相似,但提供额外的功能,如鼠标悬停、按下、释放以及键盘事件
Canvas 提供绘制形状的选择(线段、椭圆、多边形、矩形),能够包含图像和位图
Checkbutton 一组选框,能够勾选其中的任意个(和HTML中的checkbox相似)
Entry 单行文本框,用于收集键盘输入
Frame 包含其余控件的纯容器
Label 用于包含文本或图像
LabelFrame 标签和框架的组合,拥有额外的标签属性
Listbox 给用户显示一个选项列表进行选择
Menu 按下Menubutton后弹出的选项列表,用户能够从中选择
Menubutton 用于包含菜单(下拉、级联等)
Message 消息,于Label相似,不过能够显示成多行
PanedWindow 一个能够控制其余控件在其中摆放的容器控件
Radiobutton 一组按钮,其中只有一个能够按下
Scale 线型‘滑块’控件,根据已设定的起始值和终止值,给出当前设定的精确值
Scrollbar 为Text、Canvas、Listbox、Enter等支持的控件提供滚动功能
Spinbox Entry和Button的组合,容许对值进行调整
Text 多行文本框,用于收集或显示用户输入的文本
Toplevel 和Frame相似,不过他提供了一个单独的窗口容器

下面先来看看一下简单的使用:

Label控件

下面tkhello.py脚本中,展现了Tkinter应用如何启动,着重强调了Label控件:

#python 3.6

import tkinter

top = tkinter.Tk()#建立顶层窗口
label = tkinter.Label(top,text='Hello world!')#建立标签label,包含连个参数
label.pack()#使用Packer来管理和显示控件
tkinter.mainloop()#运行GUI程序。这是必须的

运行效果:

 Button控件

下面的tkhello2.py脚本中,展现了按钮控件:

#python 3.6

import tkinter

top = tkinter.Tk()#建立顶层窗口
quit = tkinter.Button(top,text='Hello World!',command=top.quit)#建立按钮quit,包含三个参数,其中第三个参数给按钮安装了一个回调函数:当按下按钮并释放后,程序就会退出
quit.pack()#使用Packer来管理和显示控件
tkinter.mainloop()#运行GUI程序。这是必须的

运行效果:

Label和Button控件

下面的tkhello3.py脚本中,结合了标签和按钮的功能,并使用了更多的参数:既包括控件的非默认参数,又展现了Packer的一些参数。fill参数告诉Packer让‘退出’按钮占据剩余的水平空间,expand参数则会引导它填充整个水平可视空间,将按钮拉伸到左右窗口边缘。同时,若是Packer没有收到其余指示,全部控件都是垂直排列的(自上而下依次排列):

 

#python 3.6

import tkinter

top = tkinter.Tk()
hello = tkinter.Label(top,text='Hello Tkinter!') #建立一个标签
hello.pack()

quit = tkinter.Button(top,text='退出',command=top.quit,bg='red',fg='white')#建立一个退出按钮,除了绑定一个回调函数外,还设置了背景色以及释放按钮时的颜色
quit.pack(fill = tkinter.X,expand=1)#

tkinter.mainloop()

 

运行效果:

Label、Button和Scale控件

下面的tkhello4.py脚本中,在以前的基础上增长了Scale控件:

#python 3.6
from tkinter import * #虽然这种写法会污染命名空间,可是这里依然使用这种写法是由于该脚本会大量引用此模块

#该函数依附于Scale控件,当Scale控件的滑块移动时,这个函数就会被激活。该函数会调整Label控件中的文本大小
def resize(ev = None):
    label.config(font = 'Helvetica -%d bold' % scale.get())
    
top = Tk()#顶层窗口
top.geometry('250x150+1000+500')#设置顶层窗口的属性,250x150是指窗口大小,1000+500是指窗口在屏幕上的位置

#建立一个Label控件,拥有默认大小的字体
label = Label(top,text = 'hello world!',font = 'Helvetica -12 bold')
label.pack(fill = Y,expand=1)#经过Packer管理和显示label控件
#建立Scale控件,该控件经过回调resize函数用来控制Label控件中字体大小的;from_属性是滑块最小值,to是滑块最大值
scale = Scale(top,from_=10,to=40,orient=HORIZONTAL,command=resize)
scale.set(30)#设置滑块的初始值
scale.pack(fill=Y,expand = 1)#经过Packer管理和显示Scale控件

#建立一个退出按钮控件,按下按钮前的颜色是白色,释放按钮后的颜色是红色
quit = Button(top,text='退出',command=top.quit,activeforeground='white',activebackground='red')
quit.pack()#经过Packer管理和显示Button控件

mainloop()#主循环

运行效果:

 tkinter结合偏函数应用实例

何谓偏函数:当函数的参数个数比较多的时候,可使用functools.partial建立一个新的函数,这个新函数会固定住(冻住)原函数的部分参数,以后,当得到须要的剩余参数后,能够将它们解冻,一块儿传入到最终的参数中,从而使用最终肯定的全部参数去调用函数。简单说就是:。functools.partial会把一个函数的某些参数设置默认值,并返回一个新函数,咱们能够直接调用这个新函数。友情连接:偏函数

偏函数的一大优势就是它不局限于函数,而是能够用于任何可调用对象(任何包括函数接口的对象),只须要使用圆括号便可,包括类、方法或可调用实例。

对于不少可调用对象,而且许多调用都反复使用相同参数的状况,使用偏函数会更合适。

GUI编程是一个很好的偏函数用例,由于你颇有可能须要GUI控件在外观上具备某种一致性,而这种一致性来自于使用相同参数建立类似的对象时。想象有这么一个应用,有不少按钮拥有相同的背景色和前景色,对于这种只有细微差异的按钮,每次都使用相同的参数建立相同的实例简直是一种负担和浪费。

下面的pfaGUI2.py脚本中,展现了一个交通路标的实例,该应用会尝试建立文字版本的路标,并将其根据标志类型进行区分,好比严重、警告、通知。而标志类型决定了建立时的颜色方案:严重级别的是白底红字,警告级别的是黄底黑字,通知级别的是白底黑字。这里,‘严禁驶入’和‘错误路线’属于严重级别,‘交通拥堵’‘火车交汇口’属于警告级别,而‘限速’和‘单行线’属于通知级别。该应用会建立这些标志的按钮,当用户按下按钮时,会弹出相应的对话框。

这里要注意的版本问题,python2.x中的tkMessageBox模块在python3.x中被重命名为messagebox,并被整合进tkinter模块中:

#python 3.6

from functools import partial#使用偏函数
from tkinter import Tk,X,Button#仅仅导入tkinter模块中用到的属性
from tkinter.messagebox import showinfo,showwarning,showerror #python 3.xb版本中对tkMessageBox重命名。这里仅仅导入三个对话框
 #python2.x中使用from tkMessageBox import showinfo,showwarning,showerror

#定义了三个标志 警告、严重、通知
WARN = 'warn'
CRIT = 'crit'
REGU = 'regu'
SIGNS = {
    '严谨驶入': CRIT,
    '火车交汇': WARN,
    '限速': REGU,
    '错误路线': CRIT,
    '交通拥堵': WARN,
    '单行线': REGU,
    'do not': CRIT
}

#对话框用做按钮的回调函数,将在建立每一个按钮时使用他们
critCB = lambda:showerror('Error','按下错误按钮')
warnCB = lambda:showwarning('Warning','按下警告按钮')
infoCB  = lambda:showinfo('Info','按下通知按钮')
#启动Tk,设置标题、位置
top = Tk()
top.title('路标')
top.geometry('250x250+700+500')#设置顶层窗口的属性,250x250是指窗口大小,1000+500是指窗口在屏幕上的位置
Button(top,text='退出',command = top.quit,bg = 'red',fg = 'white').pack() #建立一个退出按钮。设置前景色、背景色,并用Packer管理

MyButton = partial(Button,top)#建立了一个一阶偏函数,模板化Button类和根窗口top。MyButton效果至关于tkinter.Button() 并将top做为他的第一个参数
#下面是三个二阶偏函数。二阶偏函数是对一阶偏函数的再次模板化。最终效果至关于使用top、回调函数和颜色这几个参数去调用Button。
CritButton = partial(MyButton,command = critCB,bg = 'white',fg = 'red')
WarnButton = partial(MyButton,command = warnCB,bg = 'yellow')
ReguButton = partial(MyButton,command = infoCB,bg = 'white')

for eachSign in SIGNS:
    signType = SIGNS[eachSign]
    #构建一个可求值字符串cmd,该字符串包含按钮名、传给按钮标签的文本参数 和 pack()操做组成。若是是严重级别,会把字符大写,不然按照标题格式输出。这里还使用了三元操做符。格式化字符串的时候要注意%s和%r的区别.
    #标题化函数title(),即全部单词的首字母都大写,其余的字母都小写
    cmd = '%sButton(text = %r%s).pack(fill = X,expand = True)' % \
    (signType.title(),eachSign,'.upper()' if signType ==CRIT else '.title()') #
    eval(cmd)#该函数用于执行一个字符串表达式,这里是实例化按钮
    
top.mainloop()#主循环,用于启动GUI程序

运行效果图:

 

自此,咱们算是入门了。下节咱们展现一个中级的tkinter示例~咩

相关文章
相关标签/搜索