Python tkinter(GUI编程)模块最完整教程(上)

提示:下滑文章左侧可以查看目录!

1 走进tkinter世界

1.1 认识tkinter

tkinter是一个GUI开发模块,是Tcl/Tk语言在Python上的接口,可以在大部分操作系统上运行。tkinter非常的简单而且好用。tkinter模块是自带的Python模块,如果在安装Python的时候勾选了Tcl/Tk这个选项,那么使用tkinter不会有任何问题。

导入模块非常简单,但是Python3和Python2略有不同,Python3是这样的:

import tkinter

本文的示例以Python3为准,而Python2是这样的:

import Tkinter #Tkinter开头的t是大写的

不过tkinter这个名字非常长,所以我们通常习惯这么导入:

import tkinter as tk
from tkinter import *

如果导入时候就出现了错误,提示找不到_tkinter这一模块,或者调用里面的方法时出现版本错误提示,可能是因为安装时不到位,没有勾选Tk/Tcl这一选项。在安装包中选择Modify,更改Python的安装即可

接下来让我们了解一下自己tkinter的版本:

import tkinter
print(tkinter.TkVersion)

 最好是使用8.5 Version以上的tkinter,功能比较全面一些。

1.2 tkinter的坐标系与颜色格式

坐标系

组件的排放,鼠标事件等功能都少不了坐标。tkinter的坐标系和数学上习惯用的坐标系略有不同,和pygame的坐标系是一样的。

Python tkinter(GUI编程)模块最完整教程(上)_第1张图片

以左上角为起点,x轴向右延伸,y轴向下延伸。在窗口中,容器的左上角是(0, 0),不包括窗口的标题栏和菜单栏。

颜色

当在tkinter中设置颜色时,可以用两种表示颜色的方式:一种是颜色的名称,比如"green", "brown";另一种是颜色的十六进制形式,比如"#00ffff"。遗憾的是,tkinter不支持颜色RGB元组形式,不过可以把它转换成十六进制形式。

这种十六进制形式相当于:"#"+R的十六进制+G的十六进制+B的十六进制。比如(255, 255, 255)是纯白,转换成十六进制形式就变成了#ffffff。

tkinter也有一种特殊的颜色名称,叫做SystemButtonFace,是一种浅灰色,是组件的默认背景颜色。

1.3 创建根窗口

根窗口是最主要的一个窗口,根窗口最好只有一个,因为一个Tk就是一个新的Tcl/Tk解释器,解释器并不需要太多。

根窗口使用tkinter中的Tk方法创建。在窗口中,我们可以添加各种各样的控件,也称组件(widget),比如按钮、文本输入框等,我们将在后期介绍。窗口也可以有一些子窗口。当父窗口关闭后,所有的子窗口会跟着关闭,但是子窗口关闭,父窗口不会关闭。

from tkinter import *

root = Tk()
mainloop()

这一段代码创建一个窗口,并且循环显示这个窗口。mainloop方法,可以让窗口循环显示,否则运行时窗口一闪就没了。一定不要忘记mainloop!mainloop也可以用while True: root.update()这一段代替,不过mainloop更加常用一些。mainloop也可以作为窗口的一个方法,即root.mainloop()。

Python tkinter(GUI编程)模块最完整教程(上)_第2张图片

这段代码创建了一个独立的窗口,默认标题叫tk,你可以在下面的任务栏找到它。同样,你也可以自由拖拽它的位置,改变窗口的大小。也可以把它关闭、最小化、最大化。

Tk(screenName=None, baseName=None, className='Tk', useTk=1, sync=0, use=None)

Tk有一个参数叫做className,允许你改变窗口标题。但是这样改变标题有一个bug,就是窗口标题的首字母会自动小写,因此不推荐你这么做,而应使用title方法。Tk的参数并不常用,但有一些比较基础常用的方法,更多的方法,请参见2.2.14

方法 使用方法
title(string=None) 设置窗口的标题,同时返回窗口标题
geometry(newGeometry=None) 设置窗口的尺寸大小,同时返回当前窗口尺寸
iconbitmap(bitmap=None) 设置窗口的图标,需指定图标文件(*.ico)的位置
resizable(width=None, height=None) 设定是否能够改变窗口的宽和高尺寸
destroy() 销毁窗口,也就是把窗口关掉

下面看一个示例,演示了tk中一些常用的窗口操作:

from tkinter import *

root = Tk()
root.title("我的窗口")
root.iconbitmap("my_icon.ico")
root.geometry("500x500")
root.resizable(False, False)

mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第3张图片

可以看出,窗口被设置了标题"我的窗口",图标也变成了自定义的图标。由于resizable的设定,这个窗口无法改变大小,只能保持在500x500。 

下面着重讲一下geometry方法。这个方法不仅可以设置窗口的尺寸,也可以设置窗口在电脑屏幕上的位置。给定参数的格式是:widthxheight+x+y。root.geometry("300x100+20+50")代表的就是把root窗口设置为300x100的尺寸,与屏幕最左边相隔20像素,与屏幕最上方相隔50像素。可以只设置窗口的尺寸,即widthxheight;也可以只设置窗口的位置,即+x+y。geometry还有一些用法,在讲Wm类的时候会介绍。

窗口有一个默认的背景颜色,同样也是大多数tk组件的颜色。这个颜色是一种浅灰色,在tk内部称作SystemButtonFace,只能在tk中使用,其他模块是不支持这个颜色的。如果要改变窗口的背景,可以使用窗口的config方法,也可以写作configure方法。大部分控件都支持这个方法,用来定义控件后改变它的属性。

from tkinter import *

root = Tk()
root.config(bg="blue")

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第4张图片

一个纯蓝色的窗口就出现了。

1.4 组件

tkinter支持很多组件,可以帮助你完成一些功能。组件根据坐标被排列在容器(container)中,窗口的界面是该窗口中最大的容器。

tkinter的组件有:

  • Label:标签控件,用来在窗口上显示文本和图片
  • Message:消息控件,用来显示多行文本,与Label功能类似
  • Button:按钮控件,用户可以点击按钮,点击事件将会传递给设置的回调函数
  • Entry:文本输入框控件,用户可以输入文字,但只能在一行输入
  • Text:多行文本输入框控件,用户可以输入多行文字,自由换行
  • Canvas:画布控件,可以在上面显示基本图形、文字、图片
  • Frame:框架控件,作为一个小容器,相当于给组件分组。
  • LabelFrame:文字框架控件,和Frame不同的是,框架外面多了文本提示
  • Menu:菜单控件,在窗口上显示菜单,或定义弹出式菜单。
  • Menubutton:菜单按钮控件,是Button的样子,点击后弹出一个菜单。
  • Checkbutton:多选按钮,用户可以勾选或取消勾选。
  • Radiobutton:单选按钮,用户可以在同类的Radiobutton中选择一个,无法取消勾选
  • Listbox:列表框组件,可以显示一个字符串的列表
  • Scrollbar:滚动条控件,用来添加一个滚动条控制滚动
  • Scale:尺度条控件,用来添加一个数字滑块,用户可以滑动调整数值。
  • Spinbox:数字选值框控件,用户既可以输入数字,也可以按调节按钮调整数值。
  • OptionMenu:选项菜单,用户可以从下拉菜单中选择一个值,但是不能自己输入。
  • PanedWindow:分栏容器控件,和Frame类似,但是有更多的功能设定,比如用户可以调节大小
  • Toplevel:上层窗口控件,可以定义某个窗口的子窗口。

 tkinter还有一些子模块,如ttk,messagebox,colorchooser,filedialog等。

ttk中有一些扩展组件,里面有一些和主模块一样的控件,但是样子要不同。ttk有一个最大的特点,组件的字体、颜色等功能不能直接修改,而是要用ttk.Style形式修改,后期会讲述。而tkinter主模块中可以直接指定组件的颜色、字体等样式。所以,如果在from tkinter import *后继续导入from tkinter.ttk import *,就会覆盖tkinter.ttk与tkinter主模块中相同的组件,要改变字体和颜色只能使用Style的形式。这一点千万不能弄错。

tkinter.ttk的扩展组件有:

  • Combobox:组合选择框控件,用户可以自己在输入框中输入内容,也可以在下拉列表中选择。
  • Notebook:笔记本控件,添加多个Frame选项卡,用户可以在不同选项卡之间切换。
  • Progressbar:进度条控件,显示一个加载时的进度条
  • Separator:分割线控件,显示一条垂直或水平的分割线。
  • Treeview:树状图控件,显示一个表格或是树状图。
  • Sizegrip:尺寸调整控件,显示一个调整窗口尺寸的按钮。

组件都有一个参数,用来定义这个组件的父容器,大多数组件的类也都有一些共同的参数,这些参数以**kw的形式传递,如:

参数名称 作用
master 组件的父容器,一般必选
name 组件在Tcl/Tk内部的名称

bg

background

改变组件的背景(ttk没有)

fg

foreground

改变组件的前景色,一般是文本颜色
width 组件的宽,单位是像素(在文本输入类组件中,单位是字符数量)
height 组件的高,单位是像素(在文本输入类组件中,单位是字符数量)
cursor 鼠标放上组件的光标样式
relief 组件边框样式
state 组件状态,可设置为normal(普通样式),disabled(禁用),active(激活),readonly(只读)。其中normal和disabled所有组件都支持,而active,readonly只有部分组件支持。
takefocus 组件是否能获取焦点

bd

borderwidth

组件边框的宽度
activebackground 组件激活时的背景色
activeforeground 组件激活时的前景色
disabledforeground 组件禁用时的前景色
disabledbackground 组件禁用时的背景色
highlightcolor 高亮(组件获得焦点)时的边框颜色
highlightthickness 高亮边框宽度
exportselection 这个是所有含有输入功能的组件的共有参数,表示选中的内容是否可以被Misc.selection_get方法检测到,参见后文对Misc类的介绍

这意味着,你可以这么定义一个组件:Label(master=root, bg="blue")。组件的类也有一个cnf参数,传给这个参数一个字典,也可以达到定义组件的效果。上面也可以写作:Label(cnf={"master":root, "bg":"blue})。

组件也有一些共同的方法:

方法名称 作用
after(ms, func=None) 等待ms毫秒后执行一次func
bind(sequence=None, func=None) 绑定事件,检测到事件后调用func
unbind(sequence) 解除绑定事件
update() 刷新组件,一般不需要手动调用
cget(key) 返回关键字参数key的值,如:root.cget("bg")返回root的背景色
configure(**kw) 也写作config,重新改变组件的关键字参数设置
destroy() 销毁组件
focus_set() 设置输入焦点

2 tkinter主模块

tkinter有一系列的子模块,这里介绍主模块内一些方法的使用方式。

2.1 Label

本节中你将了解tk中最常用也是最简单的组件:标签。

 参考资料:Python Tkinter 标签控件(Label) | 菜鸟教程

Label(master=None, cnf={}, **kw)

参数名称 作用
text 显示的文本
font 文本的字体
image 显示的图片
bitmap 显示的位图,和image只能指定一个
textvariable 绑定的文本变量
compound 当文本和图片同时显示时,图片位于文本的方位,可以是top, bottom, left, right, center,如:设置为top表示图片位于文本上方
padx 标签内容与左右的间距
pady 标签内容与上下的间距
anchor 文本靠标签哪个方向显示,可以是n,s,w,e,ne,nw,sw,se,center,即北、南、西、东、东北、西北、西南、东南、中间,默认靠中间显示
justify 文本的对齐方式,可以是left, right, center,默认是center
wraplength 自动换行字符数量,到达数量后文本会自动换一行显示

创建Label

from tkinter import *

root = Tk()
root.geometry("200x200")

lab = Label(root, text="Hello, Tkinter!")
lab.pack()

mainloop()

创建Label的时候,先要指定master,即摆放组件的父容器。所有组件都需要这样,不然tk可能不清楚你要排放在哪个容器上面。text指定显示的文本。这样就定义好了一个Label对象,赋值给lab。lab.pack()的意思是,将定义的Label摆放到父容器上面。所有的组件都需要在定义后摆放到窗口上,不然组件显示不了。至于排放位置的设置,之后会讲述到。

运行效果如下:

 Python tkinter(GUI编程)模块最完整教程(上)_第5张图片

relief参数

relief参数设定组件的样式,大多数组件都支持relief参数。

from tkinter import *

root = Tk()
root.geometry("200x200")

lab = Label(root, text="Hello, Tkinter!", relief="sunken")
lab.pack()

mainloop()

运行效果: 

 Python tkinter(GUI编程)模块最完整教程(上)_第6张图片

 relief参数指定了组件边框的样式,一共有6种relief,分别是flat, groove, raised, ridge, solid, sunken。Label的默认relief是flat。这6种relief的效果如下:

cursor参数

参考资料:【Python cursor指针】——Python Tkinter Cursor鼠标指针属性值

cursor参数指定鼠标移动到组件上时,光标的样子。光标样式有很多,这里不再赘述,可以参考下面这个示例,它会显示光标所有的样式。鼠标放在对应Label上,会显示出当前光标样式。

cursorList = ['arrow', 'xterm', 'watch', 'hand2', 'question_arrow', 'sb_h_double_arrow', 'sb_v_double_arrow', 'fleur',
              'crosshair', 'based_arrow_down', 'based_arrow_up', 'boat', 'bogosity', 'top_left_corner',
              'top_right_corner', 'bottom_left_corner', 'bottom_right_corner', 'top_side', 'bottom_side', 'top_tee',
              'bottom_tee', 'box_spiral', 'center_ptr', 'circle', 'clock', 'coffee_mug', 'cross', 'cross_reverse',
              'diamond_cross', 'dot', 'dotbox', 'double_arrow', 'top_left_arrow', 'draft_small', 'draft_large',
              'left_ptr', 'right_ptr', 'draped_box', 'exchange', 'gobbler', 'gumby', 'hand1', 'heart', 'icon',
              'iron_cross', 'left_side', 'right_side', 'left_tee', 'right_tee', 'leftbutton', 'middlebutton',
              'rightbutton', 'll_angle', 'lr_angle', 'man', 'mouse', 'pencil', 'pirate', 'plus', 'rtl_logo', 'sailboat',
              'sb_left_arrow', 'sb_right_arrow', 'sb_up_arrow', 'sb_down_arrow', 'shuttle', 'sizing', 'spider',
              'spraycan', 'star', 'target', 'tcross', 'trek', 'ul_angle', 'umbrella', 'ur_angle', 'X_cursor']
#所有的光标样式

from tkinter import *

root = Tk()

for i in range(len(cursorList)):
    cursor = cursorList[i]
    
    Label(text=cursor, cursor=cursor, relief="groove").grid(
        column=i // 20, row=i % 20, sticky="we") #后面会讲到grid,是一种排放组件方式

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第7张图片

介绍一下常见的光标样式。不同的主题和系统可能有所不同。

arrow
xterm
watch
hand2
question_arrow
sb_h_double_arrow
sb_v_double_arrow
fleur
crosshair

font参数

font参数指定文本的字体,大多数带有文本的组件都支持这个参数。font参数指定字体的样式、大小、以及是否有加粗下划线等特殊样式。font参数可以是tkinter.font.Font对象,也可以只给一个字体名称或是字体大小数值,或是给一个元组。

lab = Label(root, text="Hello!", font=("黑体", 20)) #字体为黑体,大小20;顺序不能颠倒
lab = Label(root, text="Hello!", font=20) #只设置大小20
lab = Label(root, text="Hello!", font="黑体") #只设置字体为黑体

字体的元组后面还可以加上字体的特殊样式,一共有bold(加粗), italic(斜体),underline(下划线),overstrike(删除线)几种。可以叠加设置。

Label(root, text="加粗", font=("黑体", 20, "bold")).pack()
Label(root, text="斜体", font=("黑体", 20, "italic")).pack()
Label(root, text="下划线", font=("黑体", 20, "underline")).pack()
Label(root, text="删除线", font=("黑体", 20, "overstrike")).pack()
Label(root, text="叠加使用", font=("黑体", 20, "bold", "italic", "underline", "overstrike")).pack()

运行效果:

 Python tkinter(GUI编程)模块最完整教程(上)_第8张图片

bitmap参数

bitmap参数指定添加位图,即内置图标,有error, info, hourglass, questhead, question, warning, gray12, gray25, gray50, gray75。下面的示例列举了所有bitmap:

from tkinter import *

root = Tk()

bitmaps = ["error", "info", "hourglass", "questhead", "question", "warning",
           "gray12", "gray25", "gray50", "gray75"]
for bitmap in bitmaps:
    Label(root, text=bitmap, bitmap=bitmap, compound="left").pack()

mainloop()

compound的意思是:图片置于文字的位置,上面的参数解释有。

运行效果:

Python tkinter(GUI编程)模块最完整教程(上)_第9张图片

image参数

image参数在Label中添加图片。这个图片是一个tk.PhotoImage对象,支持的格式只有*.gif, *.ppm, *.pgm,较新版的tk支持显示*.png。注意:直接在图片文件后面改后缀不会改变图片本身的文件类型!更需要强调的一点是,图片对象必须要赋值给一个全局变量,或者是类的实例变量之类的,保证不会被Python机制回收,否则图片无法正确显示。

image = tkinter.PhotoImage(file="图片名称")

这段代码建立了一个tk图片对象,现在需要把它传递给Label。

image = PhotoImage(file="monster.gif")
Label(root, image=image, text="It's a monster.", compound="top").pack()

运行效果: 

Python tkinter(GUI编程)模块最完整教程(上)_第10张图片

 但是,如果想要显示更多的图片文件格式,比如*.jpg该怎么办呢?这时候需要使用pillow工具。这是一个第三方模块,需要用pip安装:pip install pillow,导入时import PIL。

from tkinter import *
from PIL import Image, ImageTk

root = Tk()
root.geometry("200x200")

image = ImageTk.PhotoImage(Image.open("monster.png"))
Label(root, image=image, text="It's a monster.", compound="top").pack()

mainloop()

运行效果: 

Python tkinter(GUI编程)模块最完整教程(上)_第11张图片

 这样,我们用PIL工具成功显示了png图片(不过版本较新的Tk本来也可以显示png图片)。也需要注意,在使用tkinter.PhotoImage的时候,需要指定file="文件名"这个关键字参数,但使用PIL工具则不需要指定file关键字参数。

tkinter也有一些内部的图片,可以通过字符串传递给image。

包括:"::tk::icons::error","::tk::icons::information","::tk::icons::question","::tk::icons::warning"。

它们的效果如下:

from tkinter import *

root = Tk()

for image in ["::tk::icons::error",
              "::tk::icons::information",
              "::tk::icons::question",
              "::tk::icons::warning"]:
    Label(root, text=image, image=image, compound="top").pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第12张图片

这些名字为什么这么复杂呢?其实,::是Tcl语言命名空间的表示方式,这里不多讲。

textvariable参数

tkinter提供了一些变量对象,可以绑定到组件,可以设置它们的值。绑定的组件会随着设置而刷新。这些对象有StringVar()文本变量,IntVar()整数变量,DoubleVar()浮点数变量,BooleanVar()布尔值变量。

建立一个tkinter变量的方法是:

var = tkinter.StringVar()

然后就可以设置变量的值:

var.set(value)

也可以获取变量的值:

sth = var.get()

 StringVar中可以设置文字,IntVar可以设置整数,BooleanVar可以设置True和False,等等。

Label绑定textvariable,只需要添加一个参数textvariable=var,后期如果想要更改Label中的内容,可以执行var.set(value)来更改。当然也可以使用lab.config(text=value)这样的方式。

2.2 Button

Button即按钮,可以绑定一个回调函数,用户点击时将会执行这个函数。

参考资料:Python Tkinter 按钮组件 | 菜鸟教程

Button(master=None, cnf={}, **kw)

很多tk组件都有共通性,比如带有文本的组件,大多都有text, font, textvariable这些参数。Button的参数和Label基本类似,也支持text, image, bitmap等功能。Button也有relief,按钮默认的relief是raised。与Label最不同的是,它还可以绑定一个点击事件。

参数名称 作用
command 点击按钮时运行(是一个方法)
repeatdelay 延迟多少毫秒(1000ms=1s)后进行按钮的持续触发
repeatinterval 按钮持续触发的间隔时长(毫秒)
overrelief 鼠标经过时按钮的relief样式

常用方法:

方法 作用
invoke 调用Button的command(disabled无效)
flash 使Button闪烁几次(在normal和active几次切换)

创建Button

下面我们就来创建一个Button,它可以绑定一个回调函数,点击时在屏幕上打印"你点了一下按钮"。

from tkinter import *

root = Tk()

def callback():
    print("你点了一下按钮")

button = Button(root, text="按钮", command=callback)
button.pack()

mainloop()

运行后点击按钮,可以看到如下输出。按钮可以多次点击。 

 Python tkinter(GUI编程)模块最完整教程(上)_第13张图片

activeforeground和activebackground参数

如果鼠标长按按钮,那么按钮不会被触发,而是松开鼠标后触发。这时候,按钮处于一种激活状态。我们可以设置激活时按钮的前景和背景颜色:

Button(root, text="按钮", activeforeground="blue", activebackground="yellow")

如上面这段代码,把激活时的前景色设为blue(蓝色),背景色则设为yellow(黄色)。 点击时呈现这样的效果:

repeatdelay和repeatinterval参数

这两个参数可以用于按钮的持续触发。用户长按在按钮上,经过repeatdelay毫秒的延迟后,按钮将会重复触发,每次触发的间隔是repeatinterval毫秒。

from tkinter import *

root = Tk()
root.geometry("200x200")

def addnum():
    num = int(b.cget("text")) #获取组件的参数选项
    b.config(text=str(num + 1))
    
b = Button(root, text="0", command=addnum,
           repeatdelay=1000, repeatinterval=500)
b.pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第14张图片

效果:当用户按在按钮上面不动时,经过repeatdelay毫秒(1秒)后,按钮的command每间隔repeatinterval毫秒(0.5秒)就执行一次。

禁用按钮

所有组件都有state参数,表示组件的状态。一共有三个状态:normal, disabled, active。默认的state是normal,此时用户可以点击按钮。而处于disabled禁用的按钮,用户将无法点击。active则是激活状态。

Button(root, text="按钮", state="disabled")

处于禁用状态的按钮,无法点击:

 

处于激活状态的按钮如果不进行设置是看不出来的,但是设置了activebackground和activeforeground,就可以看出按钮处于激活状态。但是点击松开之后,激活状态就会取消(变成normal状态)。

根据这个原理,我们可以做出点击一次就禁用的按钮:

from tkinter import *

root = Tk()

def disable():
    button.config(state="disabled")
    
button = Button(root, text="点击禁用", command=disable)
button.pack()

mainloop()

如果你忘了config的用法,这里再强调一次 :用于改变组件原本设定的参数,这个方法非常常用。

运行后点击一次按钮,按钮的状态由normal改为disabled,无法点击第二次。

点击后>>>

 2.3 布局管理(pack,grid,place)

上面已经提过,组件需要在创建后,摆放到屏幕上。一共有三种摆放的方式:pack, grid, place。注意:在同一个容器中,只能使用一种布局方式,要么组件都用pack,要么都用grid,要么都用place。接下来介绍一下这三个方法的参数:

pack

pack适用于简单的布局。

  • side:组件靠哪个方向排放,可以是"top", "bottom", "left", "right",分别是上下左右,默认是"top"。

 Python tkinter(GUI编程)模块最完整教程(上)_第15张图片

  • anchor:当排放组件的可用空间要多于所需空间时,组件靠哪个方向排放,可选项是八个方位和中心(n, s, w, e, nw, ne, sw, se, center)。默认是"nw"。
from tkinter import *

root = Tk()
root.geometry("200x200")

w1 = Button(root, text="多余空间靠左")
w1.pack(anchor="w")

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第16张图片

  • expand:组件适应窗口。如设置为True,当窗口中有别的可用空间时,将会自动把组件居中摆放,并且拖拽后仍然适应窗口大小。默认为False。
from tkinter import *

root = Tk()
root.geometry("200x80")

w1 = Button(root, text="W1")
w1.pack(expand=True)

w2 = Button(root, text="W2")
w2.pack(expand=True)

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第17张图片 拖拽窗口后>>>Python tkinter(GUI编程)模块最完整教程(上)_第18张图片

 如果不设置expand,则变成这样,组件不会自动适应窗口大小:

 Python tkinter(GUI编程)模块最完整教程(上)_第19张图片拖拽窗口后>>>Python tkinter(GUI编程)模块最完整教程(上)_第20张图片

  • fill:组件的填充,可选项有"x", "y", "both", "none",默认为"none"。分别表示:x方向填充,y方向填充,两个方向都填充,无填充。这将根据参数指定填充组件可用空间,一般和expand一起使用,以保证可用空间足够。(下面都设置了expand=True,窗口未拖拽时尺寸200x80)
参数设置 未拖拽时效果 拖拽后效果
fill="x" Python tkinter(GUI编程)模块最完整教程(上)_第21张图片 Python tkinter(GUI编程)模块最完整教程(上)_第22张图片
fill="y" Python tkinter(GUI编程)模块最完整教程(上)_第23张图片 Python tkinter(GUI编程)模块最完整教程(上)_第24张图片

fill="both"

Python tkinter(GUI编程)模块最完整教程(上)_第25张图片 Python tkinter(GUI编程)模块最完整教程(上)_第26张图片
fill="none" Python tkinter(GUI编程)模块最完整教程(上)_第27张图片 Python tkinter(GUI编程)模块最完整教程(上)_第28张图片
  • padx和pady:分别表示组件与外部容器在x轴和y轴的间隔。可以只提供一个数字,表示左右间隔或上下间隔,也可以提供一个两个项的元组表示左右间隔或上下间隔。不一定要一起设置。
from tkinter import *

root = Tk()

w1 = Button(root, text="Hello")
w1.pack(padx=50, pady=30) #左右间隔50,上下间隔30

root.mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第29张图片

from tkinter import *

root = Tk()

w1 = Button(root, text="Hello")
w1.pack(padx=(50, 40), pady=(30, 60)) #左间隔50,右间隔40,上间隔30,下间隔60

root.mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第30张图片

  • ipadx和ipady:表示内部与组件边框的间隔,与padx,pady使用方法类似。
from tkinter import *

root = Tk()
root.geometry("400x200")

w1 = Button(root, text="Hello")
w1.pack(ipadx=40, ipady=40)

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第31张图片  

grid

pack布局方式适合于简单的布局,在同一容器内,只能进行上下左右四方向的布局。而grid可以实现网格布局,根据行和列指定组件的位置。grid布局和pack一样都支持padx, pady, ipadx, ipady这几个参数。

  • row和column:分别指定组件排列的行和列,row和column指定以0为起点,第一行就是row=0。
from tkinter import *

root = Tk()
root.geometry("400x200")

Button(root, text="0行0列").grid(row=0, column=0)
Button(root, text="1行0列").grid(row=1, column=0)
Button(root, text="0行1列").grid(row=0, column=1)
Button(root, text="1行1列").grid(row=1, column=1)

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第32张图片

 可以看见,实现了整齐的布局。如果此时把column设置为一个很大的数字,比如999,但是容器上的组件只有1列,那么并不会把组件排放到999列,而是排放在2列的位置。

  • rowspan和columnspan:rowspan表示组件占几行的大小,columnspan表示组件占几列的大小。
from tkinter import *

root = Tk()
root.geometry("400x200")

Button(root, text="0行0列").grid(row=0, column=0)
Button(root, text="1行0列").grid(row=1, column=0)
Button(root, text="0行1列(占两行)").grid(row=0, column=1, rowspan=2)

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第33张图片

from tkinter import *

root = Tk()
root.geometry("400x200")

Button(root, text="0行0列").grid(row=0, column=0)
Button(root, text="0行1列").grid(row=0, column=1)
Button(root, text="1行0列(占两列)").grid(row=1, column=0, columnspan=2)

root.mainloop()

  Python tkinter(GUI编程)模块最完整教程(上)_第34张图片

 如果在第二段代码的基础上,不加columnspan的设置,结果就会变成这样:

 Python tkinter(GUI编程)模块最完整教程(上)_第35张图片

  • sticky:在pack布局中和anchor类似,表示组件的方位,同时也可以达到fill的功能。可以提供八个方位+center,来指定组件在可用空间中的排列位置。
from tkinter import *

root = Tk()
root.geometry("400x200")

Button(root, text="Helloooo").grid(row=0, column=0)
Button(root, text="Hiiiiii").grid(row=0, column=1)
Button(root, text="Hello").grid(row=1, column=0, sticky="e")

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第36张图片

也可以设置组件填充排放。x轴填充表示为"ew",y轴填充表示"ns",xy轴both填充设置为"nwse"Python tkinter(GUI编程)模块最完整教程(上)_第37张图片

也可以设置填充时,同时靠某个方向排放。需要提供三个参数。比如x方向填充时同时靠北(n)排放,可以设置为sticky="ewn"。

place

place布局适用于更加复杂的,需要准确摆放组件的容器。这种布局不是很常用,因为使用比较麻烦,需要提供xy坐标以及组件的width和height(以像素为单位),place布局不支持padx……几个参数。

  • x和y:组件在x轴和y轴上的位置,单位为像素。如果不清楚tkinter坐标系,可以翻回去看一下,左上角为(0, 0)。
  • anchor:组件的锚选项,可选有八个方位,以及center。意思是:组件anchor位置的坐标设置为x,y。如:anchor="n"的时候,如果x=100, y=100,那么组件的最上面的中间的那个点的位置就是(100, 100)。下面是几个例子:Python tkinter(GUI编程)模块最完整教程(上)_第38张图片
  • width和height:指定组件排放时的宽和高。
  • relx和rely:组件在x轴或y轴相对于整个容器的位置,是一个0-1之间的浮点数,表示组件位于整个容器的位置。比如想要把组件的x设在容器30%的位置,则可以把位置设为0.3.如果想要把组件居中,就设置relx=0.5, rely=0.5, anchor="center"。
  • relwidth和relheight:指定组件相对于容器的宽与高,是一个0-1之间的浮点数。组件宽是容器宽的50%,则可以把relwidth设置为0.5.

更改组件映射

规范地说,将组件排放布局到容器上,这个过程叫做映射(map)。widget.pack/grid/place()是映射一个组件,自然也有取消映射(Unmap)的方法。

这个方法是布局方法后面加上_forget,pack布局取消映射方法是pack_forget,grid则是grid_forget,place是place_forget。

调用后,相当于隐藏了这个组件。如果还想映射的话,再次调用一下pack/grid/place即可。

将组件布局,也有办法更改布局给的参数。pack_configure, grid_configure, place_configure,可以更改布局时给定的参数。

布局管理

综合使用布局管理,可以美化界面。布局的时候,组件和组件最好都空开一定距离,这样更加美观(pack和grid可以设置padx和pady)。不要把组件挤在一处,不要让窗口长宽比过大。同样,也不要让窗口大小超出屏幕大小,影响用户操作。

同一容器中只能使用一种布局方式,这就带来了一定麻烦和局限性。所以接下来将介绍Frame组件,使用它可以使布局管理更加方便。

2.4 Frame

Frame是框架的意思,让你在容器中能够创建一个子容器。使用Frame,可以对组件编组,也可以使你能够在一个窗口中综合使用不同的布局方式。比如,在窗口中使用pack布局,在窗口上的Frame中使用grid布局,这是允许的。

参考资料:Python Tkinter 框架控件(Frame) | 菜鸟教程

Frame(master=None, cnf={}, **kw)

Frame没有别的参数,只有几个基本参数,如relief, cursor, highlightcolor等。使用也很简单。

创建Frame

from tkinter import *

root = Tk()
root.geometry("200x200")

fr = Frame(root)
fr.pack()

Button(fr, text="button in frame").pack()
Button(fr, text="button2 in frame").pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第39张图片

看上去,和没有Frame也没有什么区别,我们可以给Frame加上边框(设置relief参数)。注意,设置Frame的时候必须要更改它的边框宽度,即bd(borderwidth)。

fr = Frame(root, relief="solid", bd=2)

 Python tkinter(GUI编程)模块最完整教程(上)_第40张图片

Frame的作用

Frame中可以添加容器中能添加的任何组件,甚至可以嵌套Frame。那么,使用Frame的意义是什么呢?可以参考下面几个作用:

  • 方便组件的排放:如果想要在窗口顶部横向摆放几个组件,在下面再摆一个组件,使用grid固然可以,但就比较麻烦,行列不容易调整。这时候可以加上Frame,在窗口中摆一个Frame,下面摆一个组件。再在Frame中横向摆三个组件。这样使用pack布局就能轻松完成。
from tkinter import *

root = Tk()
root.geometry("200x200")

fr = Frame(root)
fr.pack(padx=5, pady=5)

Button(fr, text="1").pack(side="left")
Button(fr, text="2").pack(side="left")
Button(fr, text="3").pack(side="left")

Button(root, text="OK").pack(pady=5)

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第41张图片

  • 方便取消映射或销毁组件:如果一个窗口中插入了大量组件,想要把其中一部分隐藏,就需要调用很多个forget,显得很麻烦 。但如果把这些需要隐藏的组件放进一个Frame,到时候只需要隐藏这个Frame,就可以把所有的组件一起隐藏掉了。
from tkinter import *

root = Tk()
root.geometry("200x200")

fr = Frame(root)
fr.pack(padx=5, pady=5)

Button(fr, text="1").pack(side="left")
Button(fr, text="2").pack(side="left")
Button(fr, text="3").pack(side="left")

Button(root, text="隐藏", command=fr.pack_forget).pack(pady=5)

mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第42张图片点击隐藏按钮>>>Python tkinter(GUI编程)模块最完整教程(上)_第43张图片

再比如,想要删除一部分组件,然后换成另外一部分组件,也可以使用Frame。只需要把这些组件放进一个Frame,然后遍历Frame的子组件,对组件挨个销毁即可。 

容器的winfo_children方法返回一个列表,包含了容器所有的子组件。destroy方法销毁一个组件,组件方法介绍时提到过。

for widget in frame.winfo_children():
    widget.destroy() #逐个销毁frame的子组件

这样可以销毁Frame中的所有组件。

2.5 LabelFrame

这个组件与Frame类似,但是可以在左上方显示一段文本或是一个组件。

LabelFrame(master=None, cnf={}, **kw)

参数名称 作用
text 显示的文本
font 文本的字体
labelanchor 文本位于Frame的方位
labelwidget 用一个组件替代显示的文本

创建LabelFrame

from tkinter import *

root = Tk()
root.geometry("200x200")

fr = LabelFrame(root, text="LabelFrame")
fr.pack(fill="both", padx=4)

Button(fr, text="1").pack()
Button(fr, text="2").pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第44张图片

labelanchor参数

labelanchor参数设置文本的位置,可选有八个方位,但不包括center,默认是nw。下面是两个示例。

Python tkinter(GUI编程)模块最完整教程(上)_第45张图片

labelwidget参数

如果你不想要LabelFrame的上面显示一段文字,也可以把它替换为别的组件,比如Button。这个组件的master不影响,只要在同一父容器中就行。

from tkinter import *

root = Tk()
root.geometry("200x200")

fr = LabelFrame(root, text="LabelFrame", labelwidget=Button(root, text="按钮"))
fr.pack(fill="both", padx=4)

Button(fr, text="1").pack()
Button(fr, text="2").pack()

mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第46张图片

2.6 Entry

Entry是一个文本框组件,用户可以在里面输入文本。

参考资料:Python ---(六)Tkinter窗口组件:Entry_近视的脚踏实地的博客-CSDN博客

Entry(master=None, cnf={}, **kw)

参数名称 作用
font 输入文本字体
show 输入文本被显示为什么字符
selectbackground 选中文字的背景色
selectforeground 选中文字颜色
insertborderwidth 光标边框宽度(指定时光标样式为raised)
insertontime 光标闪烁时,处于“亮”状态的时长(毫秒)
insertofftime 光标闪烁时,处于“灭”状态的时长(毫秒)
insertwidth 光标的宽度
selectborderwidth 选中文字的背景边框宽度
textvariable 绑定的StringVar,同步Entry输入的内容
readonlybackground 文本框处于readonly状态下的背景颜色
xscrollcommand x方向滚动条(后面介绍)
validate 验证输入合法性的条件

vcmd

validatecommand

判断输入合法性的回调函数,或者是一个包含回调和所需参数的元组

invcmd

invalidcommand

输入不合法时执行的回调函数

常用方法:

方法名称 作用
get() 获取文本框的值
delete(first, last=None) 删除文本框中从索引first到last的内容
insert(index, s) 在文本框中插入文本,index是索引,s是插入内容
select_range(start, end) 选中从start到end的文本
icursor(index) 将光标移动到索引处

创建Entry

from tkinter import *

root = Tk()
root.geometry("200x200")

ent = Entry(root)
ent.pack()

mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第47张图片

 出现了一个输入框,可以在里面自由输入内容。

show参数

指定show参数,可以使输入里面的内容显示为一个字符,常用于密码输入。下面的示例,将所有的输入内容显示为*号。

from tkinter import *

root = Tk()
root.geometry("200x200")

Label(root, text="Pwd: ").pack()

ent = Entry(root, show="*")
ent.pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第48张图片

无论输入什么内容,都是*号显示。

get方法

get方法获取文本框的值,如下示例:

from tkinter import *

root = Tk()
root.geometry("200x200")

ent = Entry(root)
ent.pack()

def printget():
    print(ent.get())
    
Button(root, text="获取输入", command=printget).pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第49张图片

点击按钮,将会输出文本框中的值。

insert和delete方法

insert方法可以插入一段内容,需要指定一个插入的位置和插入的内容。

插入位置可以是是字符的索引,比如0代表在第一个字符前面插入。也可以是一些特殊的值,比如"end"(在结尾处插入), "insert"(在光标闪烁处插入) 

delete方法则用于删除一段内容,需要指定删除的开始和结束位置。位置的设定和insert一样。

tkinter还有一些类也有这两个方法,索引的用法也都基本一样。

readonly状态

Entry可以设置为state="readonly",也就是只读状态。处于readonly的Entry不能被输入,但是用户可以选中Entry里面插入的内容,当然也可以复制。如果是disabled状态,用户不但不能输入,而且不能选中里面的内容。

输入验证

validate, validatecommand, invalidcommand这三个参数用于输入验证。输入验证,也就是判断用户在Entry里面输入的内容是否符合要求。

validate参数是输入的条件,也就是在什么情况下,开启输入验证的功能。可以有"focus", "focusin", "focusout", "key", "all", "none"这几个可选。

参数值 解释
focus 当组件获得或失去焦点时验证
focusin 当组件获得输入焦点(光标闪烁)时验证
focusout 当组件失去输入焦点时验证
key 当输入内容更改时验证,如果验证为False,输入内容不会被插入文本框
all 当上述任何一种情况出现时验证
none 不进行验证(默认值)

validatecommand是验证的函数,invalidcommand是验证失败时执行的方法。验证条件成立时,会调用validatecommand方法,这个方法要有一个True或False的返回值。如果是True,则验证通过;如果是False,则验证不通过,将会执行invalidcommand方法。

下面是一个示例,只有输入数字才会通过验证。

from tkinter import *

root = Tk()
root.geometry("200x200")

def vld():
    if e.get().isdigit():
        print("数字,符合要求")
        return True
    else:
        print("不是数字,不符合要求")
        return False

def wrong():
    print("输入不符合要求,调用invalidcommand")

    
e = Entry(root, validate="focusout", validatecommand=vld, invalidcommand=wrong)
e.pack()

mainloop()

运行效果:当输入一个数字,然后把焦点转移(激活另外一个可输入窗口)时,打印“数字,符合要求”。当输入的不是数字时,打印“不是数字,不符合要求”和"输入不符合要求,调用invalidcommand"两句。

validatecommand参数还可以给一个元组(callback, v1, v2, v3, ...),包含执行的方法和你希望Entry传递给方法的参数。

参数选项 解释
%d 传递一个操作代码:0表示删除操作,1表示插入操作,-1表示textvariable内容被程序更改或组件失去/获得焦点
%i 传递用户插入或删除内容的索引位置,如果是失去/获得焦点或textvariable内容被程序更改,传递-1
%P 传递文本框最新的输入内容
%s 传递调用验证函数前,文本框上一次的输入内容
%S 传递文本框输入或删除的内容
%v 传递当前validate参数的值
%V 传递调用验证函数的原因,是"focusin"(获得焦点), "focusout"(失去焦点), "key"(输入或删除文本框内容), "forced"(textvariable被程序修改)
%W 组件名称(Tcl内部名称)

比如,把validatecommand设为(callback, "%P", "%s"),那么在调用callback的时候会传递两个参数,一个是文本框最新的输入内容,一个是文本框上一次的输入内容。

需要说明的是,使用validatecommand传递元组的时候,不能直接传递普通的函数,需要注册为Tcl函数才能使用输入验证。注册方法是:

tcl_cmd = root.register(cmd)

下面的一个示例,演示了validatecommand传参。 

from tkinter import *

root = Tk()
root.geometry("200x200")

def vld(s):
    print("输入或删除了", s)
    return True

vld = root.register(vld) #注册为Tcl函数
e = Entry(root, validate="key", validatecommand=(vld, "%S"))
e.pack()

mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第50张图片

实例:密码验证系统

下面的一个实例中,用户需输入一串正确的密码,否则无法通过验证。

from tkinter import *

correct_pwd = "0123456789" #正确的密码

root = Tk()
root.title("密码验证系统")

def ok():
    if pwd.get() == correct_pwd:
        print("验证通过!")
        root.destroy()

    else:
        print("验证失败!")
        
pwd = Entry(root, show="*")
pwd.pack()

Button(root, text="OK", command=ok).pack()

root.mainloop()

Python tkinter(GUI编程)模块最完整教程(上)_第51张图片 

2.7 事件绑定

组件的bind方法可以使组件绑定一个事件和一个回调函数,事件有按下某个键,点击组件等,一般是由用户引发的。事件会被传递给回调函数,然后执行函数。

Widget.bind(sequence=None, func=None)

sequence是事件序列,func是检测到事件的回调函数。

参考资料:Tkinter 事件绑定

按键名称

此处只选取一些常用的按键,更多按键名请参考:keysyms manual page - Tk Built-In Commands

按键名(keysym)   按键码(keycode)       代表的按键

Alt_L                64                左边的Alt按键
Alt_R                113               右边的Alt按键
BackSpace            22                BackSpace(退格)按键
Cancel               110               break按键
Caps_Lock            66                CapsLock(大写字母锁定)按键
Control_L            37                左边的Control
Control_R            109               右边的Control
Delete               107               Delete按键
Down                 104               ↓按键
End                  103               End按键
Escape               9                 Esc按键
Execute              111               SysReq按键
F1                   67                F1按键
F2                   68                F2按键
F3                   69                F3按键
F4                   70                F4按键
F5                   71                F5按键
F6                   72                F6按键
F7                   73                F7按键
F8                   74                F8按键
F9                   75                F9按键
F10                  76                F10按键
F11                  77                F11按键
F12                  96                F12按键
Home                 97                Home按键
Insert               106               Insert按键
Left                 100               ←按键
Linefeed             54                Linefeed(Ctrl + J)
KP_0                 72                小键盘数字0
KP_1                 73                小键盘数字1
KP_2                 74                小键盘数字2
KP_3                 75                小键盘数字3
KP_4                 76                小键盘数字4
KP_5                 77                小键盘数字5
KP_6                 78                小键盘数字6
KP_7                 79                小键盘数字7
KP_8                 80                小键盘数字8
KP_9                 81                小键盘数字9
KP_Add               86                小键盘的+按键
KP_Begin             84                小键盘的中间按键(5)
KP_Decimal           91                小键盘的点按键(.)
KP_Delete            91                小键盘的删除键
KP_Divide            112               小键盘的/按键
KP_Down              88                小键盘的↓按键
KP_End               87                小键盘的End按键
KP_Enter             108               小键盘的Enter按键
KP_Home              79                小键盘的Home按键
KP_Insert            90                小键盘的Insert按键
KP_Left              83                小键盘的←按键
KP_Mutiply           63                小键盘的*按键
KP_Next              89                小键盘的PageDown按键
KP_Prior             81                小键盘的PageUp按键
KP_Right             85                小键盘的→按键
KP_Subtract          82                小键盘的-按键
KP_Up                80                小键盘的↑按键
Next                 105               PageDown按键
Num_Lock             77                NumLock(数字锁定)按键
Pause                110               Pause(暂停)按键
Print                111               PrintScrn(打印屏幕)按键
Prior                99                PageUp按键
Return               36                Enter(回车)按键
Right                102               →按键
Scroll_Lock          78                ScrollLock按键
Shift_L              50                左边的Shift按键
Shift_R              62                右边的Shift按键 
Tab                  23                Tab(制表)按键
Up                   98                ↑按键

sequence

事件序列遵从一定的格式,如果不合理将会报错:

外面由<>尖括号括起来,中间由-减号隔开。 modifier是条件,表示只有当modifier成立的时候才会执行函数,可以有多个;type是主要事件的类型,当type有detail的时候可以省略type(有时候可能弄混);Detail是事件类型的附带描述,有的事件类型需要Detail,但有的不需要。

这可能有些难懂,下面将详细解析。

type是事件的类型,下面是type的名称:

type 触发条件 detail

Button

ButtonPress

用户点击鼠标 1:鼠标左键;2:鼠标中键;3:鼠标右键;4:滑轮向上滚动(Linux);5:滑轮向下滚动(Linux)
ButtonRelease 鼠标按键释放 1:鼠标左键;2:鼠标中键;3:鼠标右键;4:滑轮向上滚动(Linux);5:滑轮向下滚动(Linux)
Active 组件被激活
Deactivate 组件失去激活
Enter 光标进入组件范围(不是按下回车键)
Leave 光标离开组件范围

Key

KeyPress

用户按下按键 可以指定具体的按键名,参见前面的按键表
KeyRelease 用户释放按键 可以指定具体的按键名,参见前面的按键表
Map 组件被映射
Unmap 组件取消映射
FocusIn 组件获得焦点
FocusOut 组件失去焦点
Configure 组件尺寸被调节或拖拽
Destroy 组件被销毁
Expose 窗口或组件的某部分不再被覆盖
Motion 光标在组件内移动
MouseWheel 鼠标滚动(Windows和Mac;Linux应为Button-4、5)
Visibility 窗口在屏幕中可见(比如还原最小化、窗口由隐藏变为显示时触发)

下面是一个示例,演示了bind方法。

from tkinter import *

def callback(event):
    Label(root, text="你点了一下").pack()

root = Tk()
root.geometry("400x200")
root.title("点击窗口")
root.bind("", callback)

mainloop()

 Python tkinter(GUI编程)模块最完整教程(上)_第52张图片点击几次窗口>>>Python tkinter(GUI编程)模块最完整教程(上)_第53张图片

事件序列中,Button是type,意思是点击鼠标,后面的1是detail,表示鼠标左键。同样,如果想要用鼠标中键可以改为Button-2,右键可以改为Button-3。如果不指定detail,只是Button,那么三个鼠标键点击都会被检测到。

callback是回调函数,它必须带有一个参数让bind方法传递。当检测到Button-1事件的时候,bind方法会将一个Event对象传递给callback函数的第一个参数,让函数中能够处理检测到事件的信息。下面就来介绍Event对象。

Event

tkinter.Event返回一个Event对象。Event对象在bind绑定时会传递给回调函数。大多数Event是所有事件类型可共用的,但有一些不是。下面是Event的属性。

属性 解释 仅限事件类型
widget 发生事件的组件
serial 事件序列号
type 事件类型
time 发生事件的时间
x 鼠标在窗口中的x位置
y 鼠标在窗口中的y位置
x_root 鼠标在整个屏幕上的x位置 Button, ButtonRelease, Key, KeyRelease, Motion
y_root 鼠标在整个屏幕上的y位置 Button, ButtonRelease, Key, KeyRelease, Motion
num 鼠标按下的键 Button, ButtonRelease
focus 窗口是否有焦点 Enter, Leave
width 窗口的宽度 Configure, Expose
height 窗口的高度 Configure, Expose
keycode 按键代码(上面的按键表中有) Key, KeyRelease
char 按键的字符 Key, KeyRelease
keysym 按键名称 Key, KeyRelease
keysym_num 按键名称的数字形式 Key, KeyRelease
state 事件状态(数字) Button, ButtonRelease, Key, KeyRelease, Enter, Leave, Motion
state 事件状态(字符串) Visibility
delta 滚轮滚动信息 MouseWheel

下面是一个用法示例。 

from tkinter import *

def callback(event):
    print("事件类型", event.type)
    print("点击了鼠标键", event.num)
    print("事件发生在组件", event.widget)

root = Tk()
root.geometry("400x200")
root.title("点击窗口")
root.bind("

 运行后点击几次窗口:

Python tkinter(GUI编程)模块最完整教程(上)_第54张图片

Modefier可以指定一些条件,条件成立的时候,才会捕获事件。

Modefier可以是以下内容:

modefier 成立条件
Alt 用户按着Alt键
Control 用户按着Ctrl键
Shift 用户按着Shift键

Button1

B1

用户按着鼠标左键

Button2

B2

用户按着鼠标中键

Button3

B3

用户按着鼠标右键

Button4

B4

用户将鼠标滚轮向上滚动(Linux)

Button5

B5

用户将鼠标滚轮向下滚动(Linux)
Double 后面的事件类型被连续两次触发,常用于:双击鼠标左键()
Triple 后面的事件类型被连续三次触发

比如,想要达到检测组合键的效果,按下Ctrl+S的时候,执行某些操作,即可表示为(bind区分大小写,会区分大写字母和小写字母),这里的Control是一个modefier,是可选的,不写也是一个合理的事件。

这个Control要和Key事件类型的Control_L和Control_R区分开来。如果要单独检测一个Ctrl键,就必须要用Control_L和Control_R,而不能使用条件,因为事件类型才是必选的。

再比如,检测双击鼠标和三击鼠标,事件分别是

bind_all方法

bind_all方法可以在一个窗口中,绑定所有的子组件。比如想要把一个窗口里面的所有组件都绑定,那么就可以用root.bind_all("", callback)。这样就不需要很麻烦地一个一个组件地绑定。

如果只是bind_all窗口里面的一个组件,那么整个窗口的组件也会被绑定。

虚拟事件

tkinter中同样可以定义自己的事件,也就是虚拟事件,事件格式略有不同,表示为<>,event是事件名,用两层尖括号括起来。当窗口检测到虚拟事件的时候,会执行绑定的回调函数并传递一个event。

既然是自定义事件,那么触发方式也需要自定。event_generate方法可以向组件发送一个事件。这个事件可以是自定义事件,也可以不是自定义事件,而是

你可能感兴趣的:(Python,python,开发语言)