Python Tkinter模块详解(后续持续补充)

声明:该文章是个人学习中写的,目的是总结及当作工具参考,有一定的借鉴成分,后续若有新发现则补充

目录

Tkinter简介

创建组件基本语法

Tkinter组件汇总

Variable 类

常见参数详解

anchor——表示文本的位置

background(简称bg)——背景色

foreground(简称fg)——前景色

font——字体

布局管理器

pack

grid

place

组件详解

Label 标签

Botton 组件

Checkbutton 多选框/Radiobotton 单选框

LabelFrame 带有标签的框架

Entry 输入框

Listbox 列表框

Scrollbar 垂直滚动条

Scale 滚动条

Text 文本组件

Indexes 用法

Marks 用法

Tag用法

部分Text技巧

Canvas 绘图

Canvas组件支持的对象

坐标系

画布对象显示的顺序

指定画布对象

OptionMenu 选项菜单

Message 消息组件

Spinbox 组件

PanedWindow 组件

Toplevel 顶级窗口

事件

事件绑定

事件序列

type部分常用关键词及含义:

modifier部分常用的关键词及含义

Event对象

Event对象的属性及含义:

键盘所有特殊案件的keysym和keycode:

标准对话框

messagebox 消息对话框

options参数设置内容

返回值

fieldialog 文件对话框

filedialog 内置函数

filedialog 参数汇总

返回值


 

Tkinter简介

Tkinter是python默认的GUI库,像python IDLE就是用Tkinter设计出来的。导入时可以直接导入:

import tkinter

简单示例:

from tkinter import *
root = Tk()  #实例化Tk类
Label1 = Label(root,text = 'hello') #在root中创建内容为“hello”的Label
Label1.pack()  #自动调节Label1尺寸
root.mainloop()  #进入消息循环

进阶示例:

import tkinter as tk

class App:
    def __init__(self, root):  #接收Tk的实例化对象root
        frame = tk.Frame(root) #在root中创建一个Frame框架
        frame.pack()           #自动调节frame尺寸
        #创建文字为“hello”的按钮,按下执行say_hello
        self.hi_there = tk.Button(frame, text="hello", fg="green", command=self.say_hello) 
        self.hi_there.pack(side=tk.LEFT) 

    def say_hi(self):
        print("Hello everyone!")

root = tk.Tk()
app = App(root)

root.mainloop()

通过上述例子可以看到发现,基本上所有tkinter设计的窗口,都要经过以下几个步骤:

  1. 实例化 Tk() 为root(名称自取)
  2. 在root中创建其他组件
  3. 调用 pack() 方法自动调节组件尺寸
  4. 执行 mainloop() 进入消息循环

 

创建组件基本语法

基本上所有的组件创建,都遵循以下语法:
创建窗体——在窗体上创建组件

窗体变量 = Tk()
组件变量 = 组件名称(窗体变量 ,组件参数)

若要指定组件格式,需在创建组件变量时,通过参数进行修改。创建组件变量后无法修改


Tkinter组件汇总

名称 含义
Button 按钮
Canvas 绘图形组件,可以在其中绘制图形
Checkbutton 复选框
Entry 文本框(单行)
Text 文本框(多行)
Frame 框架,将几个组件组成一组
Label 标签,可以显示文字或图片
Listbox 列表框
Menu 菜单
Menubutton 它的功能完全可以使用Menu替代
Message 与Label组件类似,但是可以根据自身大小将文本换行
for 单选框
Scale 滑块;允许通过滑块来设置一数字值
Scrollbar 滚动条;配合使用canvas, entry, listbox, and text窗口部件的标准滚动条;
Toplevel 用来创建子窗口窗口组件

Variable 类

有些控件如Entry输入框、Checkbutton复选框、Radiobutton单选框等。有时希望将他们的值与一个变量绑定起来:若变量自身变化,将变化同步到组件值中;若组件中的值变化,将变化同步到变量中。

如刚说的三种组件,给其中的参数 variable 或 textvariable 赋值,就需要用到Tkinter自带的 Variable 类方可实现变量绑定。

Variable类下主要有4种子类,分别对应文本型、整型、浮点型、布尔型变量:

参数 含义
StringVar() 保存一个 string 类型变量, 默认值为""
IntVar() 保存一个整型变量, 默认值为0
DoubleVar() 保存一个浮点型变量, 默认值为0.0
BooleanVar() 保存一个布尔型变量, 返回值为 0 (代表 False) 或 1 (代表 True)


对变量的值进行读写主要通过两种方法:get()、set()

在使用时,可以先将变量实例化,然后赋值给组件类,实现变量绑定。在给组件赋值后,通过get()获取变量值。
如:

from tkinter import *
root= Tk()
v1 = StringVar() #创建String型变量
Entry = Entry(root,textvariable=v1) #将变量与Entry组件绑定
Entry.pack(padx=5,pady=5)
root.mainloop()
print(v1.get())  #将输出的内容打印


运行结果如下:


在输入框中输出内容后关闭窗口,即可打印刚才输出的内容

修改一下代码,看看set()是如何运行的:

from tkinter import *
root= Tk()
v1 = StringVar() #创建string型变量
v1.set('hello')  #给变量赋初始值
Entry = Entry(root,textvariable=v1) #将变量与Entry组件绑定
Entry.pack(padx=5,pady=5)
root.mainloop()

运行结果如下:

接着,我们尝试给v1赋值为数值123,看看会不会出现什么不一样的地方:

from tkinter import *
root= Tk()
v1 = StringVar()
v1.set(123)
Entry = Entry(root,textvariable=v1)
Entry.pack(padx=5,pady=5)
root.mainloop()
print(v1.get()+1)

运行结果如下:

窗体显示并没有什么问题,能够显示123。但是关闭窗体后,将123与1相加,出现了 TypeError 异常:

我们将1修改为字符串,得到结果1231:

所以,我们可以得出一个结论:对于文本型变量,即使赋值为数值,仍然会转化为文本型
那么我们对整型变量赋值为数值会出现什么情况?修改代码如下:

from tkinter import *
root= Tk()
v1 = IntVar()
v1.set('123')
Entry = Entry(root,textvariable=v1)
Entry.pack(padx=5,pady=5)
root.mainloop()
print(v1.get()+1)  #输出结果:124

可以发现,如果我们输入的是文本型数值,仍然能自动转化为整型。但是当我们输入的不是数值型文本时,会出现什么情况?

from tkinter import *
root= Tk()
v1 = IntVar()
v1.set('hello')
Entry = Entry(root,textvariable=v1)
Entry.pack(padx=5,pady=5)
root.mainloop()
print(v1.get())

运行截图如下:

即使是赋值为纯文本值,也不会出现异常。那么关闭窗体,执行调用v1的代码,结果如下

_tkinter.TclError: expected floating-point number but got "hello"

很显然,此时获取v1的值时,出现了_tkinter.TclError异常,告诉我们赋值为文本是错误的。

由此,我们可以得出如下结论

  1. 给变量赋值时,会对值自动执行如 int() , str()等函数,将值转化为变量指定类型
  2. 即使赋值为错误的类型,也不会抛出异常
  3. 只有在获取变量错误值时,会抛出_tkinter.TclError异常

常见参数详解

anchor——表示文本的位置

除了LabelFrame组件有12个参数: ‘e’、‘s’、‘w’、‘n’、‘es’、‘ws’、‘en’、‘wn’、‘ne’、‘nw’、‘se’、‘sw’ 等十二个方位
其他的组件anchor都只有:W,S,E,N,WS,WN,ES,EN,CENTER(默认)九个方位

background(简称bg)——背景色

foreground(简称fg)——前景色

font——字体

设置字体,可以是

 

布局管理器

pack

pack的布局原则是:按添加顺序排列组件。相比于grid,pack更适合少量组件的排列。通常来说,尽量不要在同一个父组件中混合使用grid和pack。

基本语法为:

组件.pack(anchor, expand, fill, ipadx, ipady, padx, pady, side)

参数含义

  • anchor:当可用空间大于组件所需求的大小时,该选项决定组件被放置在容器的何处。可设置为: N、E、S、W、NW、NE、SW、SE、CENTER(默认值),表示9个方位
  • expand:指定当父容器增大时才是否拉伸组件,设置为Bool值
  • fill:设置组件是否沿水平或垂直方向填充。可设置为: NONE、X、Y、BOTH ,其中 NONE 表示不填充,BOTH 表示沿着两个方向填充
  • ipadx:指定组件在 x 方向(水平)上的内部留白
  • ipady:指定组件在 y 方向(垂直)上的内部留白
  • padx:指定组件在 x 方向(水平)上与其他组件的间距
  • pady:指定组件在 y 方向(垂直)上与其他组件的间距
  • side:设置组件的添加位置,可以设置为 TOP、BOTTOM、LEFT、RIGHT

示例:将一个组件放到另一个组件中,并填满

from tkinter import *

root = Tk()

listbox = Listbox(root)
listbox.pack(fill=BOTH, expand=True)

for i in range(10):
    listbox.insert(END, str(i))

mainloop()

结果如下:

Python Tkinter模块详解(后续持续补充)_第1张图片

fill 会告诉管理器,该组件将填充整个分配给他的空间,BOTH表示同时纵向横向,X表示横向,Y表示纵向;expand选项是告诉窗口管理器将父组件的额外空间也填满。

默认情况下,pack是将添加的组件依次纵向排列,可通过更改side改变排列方向

grid

grid管理器,相当于一个表格,将组件放入表格中,形成一个规范的表格布局。在使用grid排列组件时,只需要传递(row 行,column 列)参数即可。此外,使用grid并不需要指明表格的尺寸,管理器会自动计算。

示例:创建一个带头像的登陆器

from tkinter import *

root = Tk()

Label(root, text="用户名").grid(row=0, sticky=W)
Label(root, text="密码").grid(row=1, sticky=W)

Entry(root).grid(row=0, column=1)
Entry(root, show="*").grid(row=1, column=1)

photo = PhotoImage(file="image/18.gif")
Label(root, image=photo).grid(row=0, column=2, rowspan=2, padx=5, pady=5)

Button(text="提交", width=10).grid(row=2, columnspan=3, pady=5)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第2张图片

默认情况下,grid 会将组件居中显示在网格中,若需要修改方向,可以设置sticky参数来更改。sticky参数值 与组件的 anchor 参数一样,为WSEN及其组合的方位。

如果要实现合并单元格(多网格放一个组件)的操作,设置rowspan和columnspan即可(见上例)

place

place 是通过指定相对于父组件的相对位置,来实现布局的。由于不同的组件可能尺寸不一等,要让组件对齐相当麻烦,因此在布局上不如前两个管理器。但是 place 可以实现覆盖布局。如果用坐标系来解释的话:pack 是在x 或y 轴上排列,grid 则是在xy坐标系中排列,而place则是在xyz坐标系中排列。

示例:创建一个RGB三色的矩形重叠形状

from tkinter import *
root = Tk()

Label(root, bg="red").place(relx=0.5, rely=0.5, relheight=0.75, relwidth=0.75, anchor=CENTER)
Label(root, bg="green").place(relx=0.5, rely=0.5, relheight=0.5, relwidth=0.5, anchor=CENTER)
Label(root, bg="blue").place(relx=0.5, rely=0.5, relheight=0.25, relwidth=0.25, anchor=CENTER)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第3张图片

在示例中,可以看到5个参数 relx、rely、relwidth、relheight、anchor,分别表示 相对于父组件的x位置、y位置、宽度、高度及方位。前四个参数都是以父对象为基准参考的,值都在0.0~1.0中,表示相对于父组件的位置及尺寸。如要显示在父组件中间,则令relx、rely为0.5,要有父组件四分之一大,则relheight及width为0.5

组件详解

Label 标签

用于在界面上输出描述的标签,可以是文字,也可以是图片

参数 含义
Anchor 标签中文本的位置
background(bg) 背景色
foreground(fg) 前景色
borderwidth(bd) 边框宽度
width 标签宽度
height 标签高度
bitmap 标签中的位图
font 字体
compound 文本和图像的混合模式
image 标签中的图片
justify 多行文本的对齐方式
text 标签中的文本,可以使用’\n’表示换行
textvariable 显示文本自动更新,与StringVar等配合着用

示例:创建一个纯文字标签

from tkinter import *

root= Tk()
label = Label(root,text="hello")
label.pack()
root.mainloop()

运行如下:
在这里插入图片描述

Botton 组件

用于创建一个按钮,除了设置按钮格式外,可以给按钮指定一个单击时触发的函数或方法

参数 含义
anchor: 指定按钮上文本的位置
background(bg) 指定按钮的背景色
bitmap 指定按钮上显示的位图
borderwidth(bd) 指定按钮边框的宽度
command: 指定按钮消息的回调函数
cursor: 指定鼠标移动到按钮上的指针样式
font: 指定按钮上文本的字体
foreground(fg) 指定按钮的前景色
height: 指定按钮的高度
image: 指定按钮上显示的图片
state: 指定按钮的状态(disabled)
text: 指定按钮上显示的文本
width: 指定按钮的宽度
padx 设置文本与按钮边框x的距离,还有pady
activeforeground 按下时前景色
textvariable 可变文本,与StringVar等配合着用

Checkbutton 多选框/Radiobotton 单选框

Radiobotton为常见的单选框,根据是否选中,返回0、1
Checkbutton为常见的多选框,根据是否选中,返回0、1

参数 含义
text 显示文本内容
command 指定Radiobutton的事件处理函数
image 可以使用gif图像,图像的加载方法img = PhotoImage(root,file = filepath)
bitmap 指定位图,如bitmap= BitmapImage(file = filepath)
value 指定同一组的单选框的值
variable 控制变量,跟踪Radiobutton的状态,On(1),Off(0)
master 代表了父窗口
bg 背景色,如bg=”red”, bg="#FF56EF"
fg 前景色,如fg=”red”, fg="#FF56EF"
font 字体及大小,如font=(“Arial”, 8),font=(“Helvetica 16 bold italic”)
height 设置显示高度、如果未设置此项,其大小以适应内容标签
relief 指定外观装饰边界附近的标签,默认是平的,可以设置的参数:flat、groove、raised、ridge、solid、sunken
width 设置显示宽度,如果未设置此项,其大小以适应内容标签
wraplength 将此选项设置为所需的数量限制每行的字符,数默认为0
state 设置组件状态;正常(normal),激活(active),禁用(disabled)
selectcolor 设置选中区的颜色
selectimage 设置选中区的图像,选中时会出现
underline With the default value of -1, none of the characters of the text label are underlined. Set this option to the inde
bd 设置Radiobutton的边框大小;bd(bordwidth)缺省为1或2个像素
textvariable 设置Radiobutton的textvariable属性,文本内容变量
padx 标签水平方向的边距, 默认为1像素
pady 标签竖直方向的边距, 默认为1像素.
justify 标签文字的对齐方向, 可选值为 RIGHT, CENTER, LEFT, 默认为 CENTER

LabelFrame 带有标签的框架

与常规的Frame框架不同,LabelFrame框架带有Label标签,该标签可以是文字也可以是GUI组件。是Frame的升级版,可以让组件分组更加简洁直观

参数 含义
bg The normal background color displayed behind the label and indicator.
bd The size of the border around the indicator. Default is 2 pixels.
cursor If you set this option to a cursor name (arrow, dot etc.), the mouse cursor will change to that pattern when it is over the checkbutton.
font The vertical dimension of the new frame.
height The vertical dimension of the new frame.
labelAnchor 设置标签的位置。该选项支持 ‘e’、‘s’、‘w’、‘n’、‘es’、‘ws’、‘en’、‘wn’、‘ne’、‘nw’、‘se’、‘sw’ 这 12 个边项值,用于控制标签的位置。
highlightbackground Color of the focus highlight when the frame does not have focus.
highlightcolor Color shown in the focus highlight when the frame has the focus.
highlightthickness Thickness of the focus highlight.
relief With the default value, relief=FLAT, the checkbutton does not stand out from its background. You may set this option to any of the other styles
text Specifies a string to be displayed inside the widget.
width Specifies the desired width for the window.

Entry 输入框

用于输入信息,如用户名密码等。

参数 含义
background(bg) 文本框背景色;
foreground(fg) 前景色;
selectbackground 选定文本背景色;
selectforeground 选定文本前景色;
borderwidth(bd) 文本框边框宽度;
font 字体;
show 文本框显示的字符,若为*,表示文本框为密码框;
state 状态;
width 文本框宽度
textvariable 可变文本,与StringVar等配合着用
validate 设置验证类型
validatecommand 指定一个验证函数,函数返回值为Bool
invalidatecommand 当validatecommand返回False时调用

 获取组件中的内容,可以设置variable类变量,也可以直接使用get()方法
插入内容使用 insert() 方法,删除内容使用 delete() 方法。
如删除所有内容:Entry.delete(0,END)
插入指定文本:Entry.insert(0,"指定文本")

示例:创建一个登录框

from tkinter import *
root = Tk()
root.title("示例")
Label(root,text="用户名").grid(row=0)
Label(root,text="密码").grid(row=1)
e1 = Entry(root)
e2 = Entry(root,show="*")
e1.grid(row=0,column=1,padx=10,pady=5)
e2.grid(row=1,column=1,padx=10,pady=5)

def extract():
    print('用户名:',e1.get())
    print('密码:',e2.get())
    e1.delete(0,END)
    e2.delete(0,END)
Button(root,text="登录",width=10,command=extract).grid(row=3,column=0,padx=10,pady=5,sticky=W) #sticky表示位置
Button(root,text="退出",width=10,command=root.quit).grid(row=3,column=1,padx=10,pady=5,sticky=E)
mainloop()

 运行如下:

Python Tkinter模块详解(后续持续补充)_第4张图片

除了基本的输入信息之外,Entry组件还支持验证功能,用于判断输入内容是否“合法”

首先需要设置validate参数,作为开启验证功能的开关。可设置的值如下:

含义

focus

当 Entry 组件获得或失去焦点的时候验证
focusin 当 Entry 组件获得焦点的时候验证
focusout

当 Entry 组件失去焦点的时候验证

key 当输入框被编辑的时候验证
all 当上面任何一种情况出现时验证
none 关闭验证功能(默认值),注:是字符串 none 而不是None

其次设置 validatecommand 参数,指定一个返回值为True 或 False 的验证函数
最后,当 validatecommand 指定的函数返回 False 时,触发 invalidatecommand 参数指定的返回值为bool类型的函数

示例:创建一个验证框,用户名为 admin 时输出“名称合法”,否则“请重新输入”

from tkinter import *

def func1():
    if e1.get() == "admin":
        print('名称合法')
        return True
    else:
        return False
def func2():
    print("请重新输入")
    e1.delete(0,END)
    return True

root = Tk()
root.title("示例")
Label(root,text="用户名").grid(row=0)
Label(root,text="密码").grid(row=1)
#当用户框失去焦点时验证
e1 = Entry(root,validate="focusout",validatecommand=func1,invalidcommand=func2) 
e2 = Entry(root,show="*")
e1.grid(row=0,column=1,padx=10,pady=5)
e2.grid(row=1,column=1,padx=10,pady=5)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第5张图片

若设置为key,需要单次输入符合条件的内容,否则无法输入

使用验证功能时,还可以设置一些额外参数:

参数 含义
%d 操作代码:0 表示删除操作;1 表示插入操作;2 表示获得、失去焦点或textvariabel值被修改
%i 当用户尝试插入或删除操作时,该参数表示插入或删除的位置(索引号),如果是因为获得、失去焦点或 textvariable 值被修改而调用验证函数,那么值为 -1
%P

当输入框的值允许改变的时候,该值有效。该值为输入框的最新文本内容

%s 该值为调用验证函数前输入框的文本内容
%S 当插入或删除操作触发验证函数的时候,该值有效。该参数表示文本被插入和删除的内容
%v 该组件当前的 validte 参数的值

%V

调用验证函数的原因,该值是“focusin”,“focusout”,“key”或“forced”(textvriable 参数值被修改)中的一个
%W 该组件的名字

使用这些额外参数前,需要先使用register()方法将验证函数包装,再将包装后的验证函数和额外参数组合为元组传递

以上面的例子为例,修改一下:

from tkinter import *

def func1(act,index,content,old_content,validate,reason,name):
    if e1.get() == "admin":
        print('名称合法')
        print(act,index,content,old_content,validate,reason,name)
        return True
    else:
        print('请重新输入')
        print(act,index,content,old_content,validate,reason,name)
        return False
root = Tk()
root.title("示例")
Label(root,text="用户名").grid(row=0)
Label(root,text="密码").grid(row=1)
test = root.register(func1)
e1 = Entry(root,validate="focusout",validatecommand=(test,"%d","%i",'%P','%s','%v','%V','%W'))
e2 = Entry(root,show="*")
e1.grid(row=0,column=1,padx=10,pady=5)
e2.grid(row=1,column=1,padx=10,pady=5)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第6张图片

调用验证函数,输出结果为:
名称合法
-1 -1 admin admin focusout focusout .!entry

Listbox 列表框

当页面空间有限,而选项比较多时,使用列表框来存放诸多选项是比较好的选择

参数 含义
master 代表了父窗口
bg 背景色,如bg=”red”, bg="#FF56EF"
fg 前景色,如fg=”red”, fg="#FF56EF"
height 设置显示高度、如果未设置此项,其大小以适应内容标签
relief 指定外观装饰边界附近的标签,默认是平的,可以设置的参数:flat、groove、raised、ridge、solid、sunken
width 设置显示宽度,如果未设置此项,其大小以适应内容标签
state 设置组件状态;正常(normal),激活(active),禁用(disabled)
bd 设置Button的边框大小;bd(bordwidth)缺省为1或2个像素
selectmode

选择模式:

SINGLE(单选) ROWSE(可通过鼠标或方向键改变的单选)

MULTIPLE(多选) EXTENDED(可通过shift和ctrl配合使用,或鼠标拖动进行的多选)

listvariable 设置listvariable属性

创建Listbox时,内容为空,需要手动添加内容。若内容较多,应使用循环添加

示例:创建一个单击按钮删除选项的 Listbox:

from tkinter import *

root = Tk()

# 创建一个空列表
theLB = Listbox(root, setgrid=True)
theLB.pack()

# 往列表里添加数据
for item in ["钢铁侠", "蜘蛛侠", "绿灯侠", "神奇女侠"]:
    theLB.insert(END, item)

theButton = Button(root, text="删除", command=lambda x=theLB: x.delete(ACTIVE))
theButton.pack()

mainloop()

但是有一个问题:Listbox 默认显示数量为10条,如果有超过10条的记录,该如何操作呢?
有两个方法:修改Listbox的height选项;添加Scrollbar 滚动条

Scrollbar 垂直滚动条

Scrollbar 滚动条虽然是一个单独组件,但是通常配合其他组件一起使用,起到辅助显示内容的作用

若要为某个组件安装垂直滚动条,需要以下两步:

  1. 设置该组件的yscrollbarcommand选项为Scrollbar组件的set()方法
  2. 设置Scrollbar 组件的command选项为该组件的yview()方法
参数 含义
master 代表了父窗口
bg 背景色,如bg=”red”, bg="#FF56EF"
relief 指定外观装饰边界附近的标签,默认是平的,可以设置的参数:flat、groove、raised、ridge、solid、sunken
width 设置显示宽度,如果未设置此项,其大小以适应内容标签
bd 设置Button的边框大小;bd(bordwidth)缺省为1或2个像素

示例:创建一个带有滚动条的Listbox

# p17_19.py
from tkinter import *
root = Tk()

sb = Scrollbar(root)
sb.pack(side=RIGHT, fill=Y)

lb = Listbox(root, yscrollcommand=sb.set) #设置yscrollcommand选项为Scrollbar的set()方法

for i in range(1000):
    lb.insert(END, str(i))

lb.pack(side=LEFT, fill=BOTH)

sb.config(command=lb.yview) #设置comand参数为组件的yview()方法

mainloop()

运行如下:
Python Tkinter模块详解(后续持续补充)_第7张图片

设置滚动条属性为组件的yview()方法,表示:当用户操作滚动条时,滚动条触发组件的yview()方法,使内容滚动

设置组件属性为set()方法的含义表示:内容的滚动会调用Scrollbar的set()方法,使滚动条滚动到相应位置

Scale 滚动条

Scale与Scrollbar类似,但是不同的是,Scale是通过滑块表示某个范围的数值

参数 含义
from_ 设置该 Scale 的最小值(由于from是python关键字,故需要加下划线 from_)
to 设置该 Scale 的最大值
resolution 设置该 Scale 滑动时的步长
label 为 Scale 组件设置标签内容
length 设置轨道的长度
width 设置轨道的宽度
troughcolor 设置轨道的背景色
sliderlength 设置轨道的长度
sliderrelief 设置滑块的立体样式
showvalue 设置是否显示当前值
orient 设置方向。该选项支持 VERTICAL 和 HORIZONTAL 两个值
digits 设置有效数字至少要有几位
variable 用于与变量进行绑定
command 用于为该 Scale 组件绑定事件处理,函数或方法

示例:创建一个窗体,当单击按钮时,获取两个Scale组件的数值

from tkinter import *

root = Tk()

s1 = Scale(root, from_=0, to=42)
s1.pack()

s2 = Scale(root, from_=0, to=200, orient=HORIZONTAL)
s2.pack()

def show():
    print(s1.get(), s2.get())

Button(root, text="获得位置", command=show).pack()

mainloop()

运行如下:
Python Tkinter模块详解(后续持续补充)_第8张图片

输出结果为:12 85

还可设置 resolution 控制分辨率(类似步长),设置 tickinterval 设置刻度

from tkinter import *

root = Tk()
#步长为5,刻度为5
Scale(root, from_=0, to=42, tickinterval=5, length=200, resolution=5, orient=VERTICAL).pack()
#步长为1,刻度为10
Scale(root, from_=0, to=200, tickinterval=10, length=600, orient=HORIZONTAL).pack()

mainloop()

运行如下:
Python Tkinter模块详解(后续持续补充)_第9张图片

Text 文本组件

Text 组件用于显示和处理多行文本,同样也可以作为简单的文本编辑器和网页浏览器

参数 含义
background(bg) 文本框背景色
foreground(fg) 前景色
selectbackground 选定文本背景色
selectforeground 选定文本前景色
borderwidth(bd) 文本框边框宽度
font 字体
show 文本框显示的字符,若为*,表示文本框为密码框
state 状态
width 文本框宽度
textvariable 可变文本,与StringVar等配合着用

text 组件与 Entry 组件类似,创建时也是没有内容的,需要通过insert()方法来插入内容。而除了常规的文字内容外, text还可以插入window组件或者image图像

示例:

from tkinter import *

root = Tk()

text = Text(root, width=20, height=5)
text.pack()
text.insert(INSERT, "Hello everyone")
b1 = Button(text, text="ok")
text.window_create(INSERT, window=b1)

mainloop()

运行如下:
Python Tkinter模块详解(后续持续补充)_第10张图片

若需要在末尾创建图像,则使用 text.image_create(END , image=image)

Indexes 用法

Indexes表示索引,主要用于定位。Tkinter也提供了一系列的索引类型

  • "line.column"(行.列)

表示第 line 行第 column 列,中间用”.“分隔行号列号,字符串或者浮点型都可识别。如”1.6“、2.5分别表示第1行第6列,第2行第5列。

需要注意的是:行号从1开始,列号从0开始,且若设置的行列号超过实际行列号,并不会报错,而是认为”已有内容末尾的下一个位置“

  • "line.end"

表示该行最后一个字符。如获取第一行第2至最后一个字符:text.get(”1.2“,"1.end")

  • INSERT(或insert)

插入光标的位置

  • CURRENT(或current)

与鼠标坐标最接近的位置(若长按任一按钮,直到松开时才会响应)

  • END(或end)

text文本缓冲区的最后一个位置的下一个位置

  • user-defined marks

用户自定义的marks(marks见后文)

  • User-defined tags

用户自定义的tags(tag见后文)

  • selection(SEL_FIRST,SEL_LAST)

是一个特殊的tag,表示当前被选中的范围,可用SEL_FIRST、SEL_LAST表示该范围,若未选中内容,则抛出TclError异常

  • window coordinate(@x,y)

使用窗口坐标作为索引,如在事件绑定中,可通过以下代码找到最接近鼠标的位置:

"@%d,%d" % (event.x,event.y)
  • embedded object name (window, images)

用于指向在Text组件中嵌入的window和image对象

要引用一个window,只要简单地将一个Tkinter组件实例作为索引即可。

引用一个嵌入的image,只需使用相应的PhotoImage和BitmapImage对象

expression

用于修改任何格式的索引,是用字符串的形式实现修改索引的表达式。具体如下:

表达式 含义
”+ count chars" 将索引向前(右)移动count个字符。可以越过换行符,但是不能超过END的位置
”- count chars" 将索引向后(左)移动count个字符。可以越过换行符,但是不能超过"1.0"的位置
”+ count lines" 将索引向前(右)移动count行。索引会尽量保持与移动前在同一列,若移动后的行字符不够前一行,则移动至行尾
”- count lines" 将索引向后(左)移动count行。索引会尽量保持与移动前在同一列,若移动后的行字符不够前一行,则移动至行尾
" linestarrt" 将索引移动至当前索引行的行首。注:使用该表达式前需有一个空格隔开
" lineend 将索引移动至当前索引行的行尾。注:使用该表达式前需有一个空格隔开
" wordstart" 将索引移动到当前索引指向的单词的开头。单词的定义是:一系列字母、数字、下划线或任意非空白字符的组合。注:使用该表达式前需有一个空格隔开
" wordend" 将索引移动到当前索引指向的单词的结尾。单词的定义是:一系列字母、数字、下划线或任意非空白字符的组合。注:使用该表达式前需有一个空格隔开

只要结果不产生歧义,可以缩写关键字及省略空格,如”+ 5 chars"可以简写为"+5c"

示例:删除光标前一个字符

def backspace(event):
    event.widget.delete("%s-1c" % INSERT,INSERT)

Marks 用法

Mark(标记)通常是嵌入到Text组件中的不可见对象。text 默认包含3中marks:INSERT、CURRENT、user-defined marks

其中INSERT用于指定当前插入光标的位置,会绘制一个闪烁的光标(因此并非mark都不可见)

如果需在一个Mark前插入或删除文本,Mark会跟着一起移动。创建Mark需使用 mark_set()方法,删除Mark周围字符不会影响Mark

示例:插入语句“hello everyone”,将两个l中间的位置创建名为split的mark,并在该mark处插入空格

from tkinter import *

root = Tk()

text = Text(root, width=20, height=5)
text.pack()
text.insert(INSERT, "Hello everyone")
text.mark_set("split","1.3")
text.insert("split"," ")

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第11张图片

删除自定义的Mark可使用mark_unset()方法,如删除上述的split标记 :text.mark_unset("split")

Tag用法

Tag(标签),通常用于改变Text组件中内容的样式和功能,可用来修改文本的字体、尺寸和颜色。另外,Tag 还允许将文本、嵌入的组件和图片与键盘和鼠标等事件相关联。

除了用户自定义的Tag,Tkinter还预设了一个特殊的Tag: SEL

创建Tag使用tag_add方法
示例:创建一个Tag1,内容为He、every,并设置为黄底蓝字
 

from tkinter import *

root = Tk()

text = Text(root, width=30, height=5)
text.pack()

text.insert(INSERT, "Hello everyone")

text.tag_add("tag1", "1.0", "1.2", "1.6","1.11")
text.tag_config("tag1", background="yellow", foreground="blue")

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第12张图片

使用tag_config()方法可以设置Tag的样式,关于tag_config()方法的参数,在此不一一列举

若对同一个文本添加多个Tag,新的Tag会覆盖旧的Tag,可以使用tag_raise()、lower()方法提升或降低Tag的优先级。
如降低名为 split 的tag的优先级:text.tag_lower("split")

除了修改格式,Tag还可以进行事件绑定。绑定事件时使用tag_bind()方法

示例:当鼠标进入every文本段时,鼠标样式切换为“arrow”形态,离开时切换回“xtrem”

from tkinter import *
root = Tk()
text = Text(root, width=30, height=5)
text.pack()
text.insert(INSERT, "Hello everyone")
text.tag_add("tag1", "1.6", "1.11")
text.tag_config("tag1", foreground="red")

def show_hand_cursor(event):
    text.config(cursor="arrow")

def show_arrow_cursor(event):
    text.config(cursor="xterm")#xterm

text.tag_bind("tag1", "", show_hand_cursor)
text.tag_bind("tag1", "", show_arrow_cursor)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第13张图片

部分Text技巧

(1)判断内容是否变化

如关闭时判断内容是否进行修改,若修改则提醒。可通过Text组件中文本的MD5来判断内容是否变化。
使用MD5时,需要导入 hashlib 模块,再将文本内容传入
示例:创建一个getSig函数,获取文本的MD5值

import hashlib
def getSig(content):
    m = hashlib.md5(content)
    return m.digest()

(2)查找内容

使用search()方法可以搜索Text组件中的内容,可以提供一个确切的目标进行搜索(默认),也可以使用Tcl格式的正则表达式进行搜索(需设置 regexp 选项为True)。如在全文中查找目标文本:pos = text.search("目标文本",start,stopindex=END)
如果忽略stopindex选项,表示到末尾,若设置backwords为True,表示修改搜索方向为向后搜索。此时start应为END

(3)撤销、恢复操作

使用text.undo()表示撤销
使用text.redp()表示恢复

撤销和恢复只能处理一次“操作”,那么什么样的算一次“操作”呢?

默认操作:焦点切换、按下回车键、删除/插入操作的转换
那么,自定义“插入一个字符”算一个操作,使用撤销/恢复时操作也是处理一个字符。那么需要绑定键盘事件,在事件触发时,插入一个“分隔符”表示分隔操作。插入分隔符,可使用edit_separator()方法

示例:

from tkinter import *
root = Tk()
text = Text(root, width=30, height=5, autoseparators=False, undo=True, maxundo=10)
text.pack()

def callback(event):
    text.edit_separator()

text.bind('', callback)
text.insert(INSERT, "Hello everyone")

def show():
    text.edit_undo()

Button(root, text="撤销", command=show).pack()
mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第14张图片

Canvas 绘图

Canvas 通常用于显示和绘制图形,可以通过它回值直线、圆形、多边形甚至是其他组件

参数 含义
background(bg) 背景色
foreground(fg) 前景色
borderwidth 组件边框宽度
width 组件宽度
height 高度
bitmap 位图
image 图片

在Canvas组件上绘制对象,可以用create_xxx()方法(xxx表示对象类型,如直线line,矩形rectangle,文本text等)

示例:创建一个蓝色的矩形:
 

from tkinter import *
root = Tk()

w = Canvas(root, width=200, height=100)
w.pack()
w.create_rectangle(50, 25, 150, 75, fill="blue")
mainloop()

 运行如下:

Python Tkinter模块详解(后续持续补充)_第15张图片

绘制矩形时,4个位置参数分别表示:左上角点的x、左上角点的y、右下角点的x、右下角点的y。
那么,绘制一个圆形呢?这时就需要用到create_oval()

from tkinter import *
root = Tk()
w = Canvas(root, width=200, height=100)
w.pack()
w.create_oval(70,20,130,80)

mainloop()

 运行如下:可以发现,绘制一个圆也是指定左上角右下角的点坐标。通过更改坐标可以绘制任意形状的圆、椭圆

Python Tkinter模块详解(后续持续补充)_第16张图片

那么,绘制一个多边形,则需要使用create_polygon(),以绘制一个国旗上的五角星为例:
 

from tkinter import *
import math as m
root = Tk()

w = Canvas(root, width=200, height=100, background="red")
w.pack()

center_x = 100
center_y = 50
r = 50

points = [
    # 左上点
    center_x - int(r * m.sin(2 * m.pi / 5)),
    center_y - int(r * m.cos(2 * m.pi / 5)),
    # 右上点
    center_x + int(r * m.sin(2 * m.pi / 5)),
    center_y - int(r * m.cos(2 * m.pi / 5)),
    # 左下点
    center_x - int(r * m.sin(m.pi / 5)),
    center_y + int(r * m.cos(m.pi / 5)),
    # 顶点
    center_x,
    center_y - r,
    # 右下点
    center_x + int(r * m.sin(m.pi / 5)),
    center_y + int(r * m.cos(m.pi / 5)),
    ]

w.create_polygon(points, outline="yellow", fill="yellow")
mainloop()

 运行如下:

Python Tkinter模块详解(后续持续补充)_第17张图片

由于五角星涉及三角函数,故需要导入math模块。

由此,可以发现:向Canvas传递位置参数时,可以是一个一个参数,也可以是由参数组成的列表或者元组。参数分别表示第一个点的xy,第二个点的xy……

既然存在画布工具,那么可不可以做到鼠绘呢?很显然,不能,因为Tkinter并没有提供自由画点的方法。所以只能偷天换日——画一个极小的圆代替点。此时,为了获取鼠标轨迹,就需要绑定事件了:

from tkinter import *
root = Tk()
w = Canvas(root, width=400, height=200)
w.pack()

def paint(event): #获取鼠标在组件内移动的x,y
    x1, y1 = (event.x - 1), (event.y - 1)
    x2, y2 = (event.x + 1), (event.y + 1)
    w.create_oval(x1, y1, x2, y2, fill="black")

w.bind("", paint) #绑定事件:按住鼠标左键时在组件内移动的轨迹
Label(root, text="按住鼠标左键并移动即可开始自由绘制").pack(side=BOTTOM)

mainloop()

 运行如下:

Python Tkinter模块详解(后续持续补充)_第18张图片

由于每次画点都是通过事件触发,每次事件触发的时间间隔基本固定,因此绘制的图像类似于打点计时器绘制的图像,速度快的地方点少,速度慢的地方点多。

Canvas组件支持的对象

  • arc(弧形、弦或扇形)
  • bitmap(内建的位图文件或XBM格式的文件
  • image(BitmapImage或PhotoImage的实例对象
  • line(线)
  • oval(圆形或椭圆形)
  • polygon(多边形)
  • rectangle(矩形)
  • text(文本)
  • window(组件)

其中,弦、扇形、椭圆形、圆形、多边形和矩形这些“封闭式”图形都是由轮廓线和填充颜色组成,可通过outline和fill选项设置他们的颜色,还可以设置为透明(传入空字符)

坐标系

由于画布可能比窗口大(带有滚动条),因此Canvas组件可以选择使用两种坐标系:
窗口坐标系:以窗口的左上角为坐标原点
画布坐标系:以画布的左上角为坐标原点

画布对象显示的顺序

在画布中创建的画布对象都会被列入显示列表中,下方的图形越接近背景。这一点有点像PS中的图层,新创建的图像会显示在旧图像的上层,在图层关系中也是上层。当然,组件中的显示列表也和图层一样,可以被重新排序

指定画布对象

Canvas组件提供几种方法来指定画布对象

  • Item handles
  • Tags
  • ALL
  • CURRENT

Item handles是一个用于指定某个画布对象的整型数(也称画布对象的ID)。当在Canvas组件上创建一个画布对象的时候,Tkinter将自动为其指定一个在Canvas中独一无二的整型值,然后各种Canvas方法可以通过这个值操纵该画布对象。

Tag是附在画布对象上的标签,Tag由普通的非空白字符串组成。一个画布对象可以与多个Tag相关联,一个Tag也可以用于描述多个画布对象。然而,与Text组件不同,没有指定画布对象的tag不能进行事件绑定和配置样式。即Canvas组件的Tag仅为画布对象所有。

Canvas预设了两个Tags:ALL和CURRENT

  • ALL(或“all”)表示Canvas中的所有画布对象
  • CURRENT(或“current”)表示鼠标指针下的画布对象

用于实现顶级菜单、下拉菜单和弹出菜单

函数

描述

bg

背景色,如bg=”red”, bg="#FF56EF"

fg

前景色,如fg=”red”, fg="#FF56EF"

font

字体及大小,如font=("Arial", 8),font=("Helvetica 16 bold italic")

relief

指定外观装饰边界附近的标签,默认是平的,可以设置的参数:flat、groove、raised、ridge、solid、sunken

selectcolor

设置选中区的颜色

bd

设置Checkbutton的边框大小;bd(bordwidth)缺省为1或2个像素

创建顶级菜单时,创建的也是空白组件,需要通过add_command()方法添加顶级菜单。

而创建下拉菜单,需要先创建下拉菜单,再在将其绑定在顶级菜单中
如:创建开始、编辑菜单,下拉菜单中各有3个选项,第一个下拉菜单每个选项中添加一个分割线,第二个下拉菜单在与顶级菜单分界处创建横线分割线

from tkinter import *
root = Tk()
menubar = Menu(root)
# 创建一个下拉菜单“文件”,然后将它添加到顶级菜单中
filemenu = Menu(menubar, tearoff=False)
items=['打开','保存','另存为']
for item in items:
    filemenu.add_command(label=item)
    filemenu.add_separator()
menubar.add_cascade(label="开始", menu=filemenu)

# 创建另一个下拉菜单“编辑”,然后将它添加到顶级菜单中
editmenu = Menu(menubar, tearoff=True)
items = ['插入','删除','复制']
for item in items:
    editmenu.add_command(label=item)
menubar.add_cascade(label="编辑", menu=editmenu)

# 显示菜单
root.config(menu=menubar)

 运行如下:

Python Tkinter模块详解(后续持续补充)_第19张图片Python Tkinter模块详解(后续持续补充)_第20张图片

在代码中实例化了两次Menu,还出现了不一样的代码。为了便于理解,绘制一个示意图,表示整个Menu的结构

Python Tkinter模块详解(后续持续补充)_第21张图片

第一次实例化创建的是一个空白导航栏,第二次实例化创建的是空白下拉菜单。对下拉菜单添加完按钮后,将其指定给导航栏的某个标签(同时创建该标签)。最后通过root.config()指定显示哪个导航栏(若创建了多个导航栏)。

示例:创建一个可切换的导航栏,单击第一个标签下拉菜单的【转换】按钮,切换至另一个导航栏

from tkinter import *
root = Tk()
root.title("First")
menubar = Menu(root)
menubar2 = Menu(root)
def call1():
    root.title("First")
    root.config(menu=menubar)
def call2():
    root.title("Second")
    root.config(menu=menubar2)
# 创建一个带转换按钮的导航栏
changemenu = Menu(menubar, tearoff=False)
item='转换'
changemenu.add_command(label=item,command=call2)
menubar.add_cascade(label="操作", menu=changemenu)

filemenu = Menu(menubar, tearoff=False)
items=['打开','保存','另存为']
for item in items:
    filemenu.add_command(label=item)
menubar.add_cascade(label="文件", menu=filemenu)

editmenu = Menu(menubar, tearoff=False)
items = ['插入','删除','复制']
for item in items:
    editmenu.add_command(label=item)
menubar.add_cascade(label="编辑", menu=editmenu)

changemenu = Menu(menubar2, tearoff=False)
item='转换'
changemenu.add_command(label=item,command=call1)
menubar2.add_cascade(label="操作", menu=changemenu)

othermenu = Menu(menubar2, tearoff=False)
items = ['帮助','升级','关于']
for item in items:
    othermenu.add_command(label=item)
menubar2.add_cascade(label="其他", menu=othermenu)

# 显示菜单
root.config(menu=menubar)
mainloop()

 运行如下:

Python Tkinter模块详解(后续持续补充)_第22张图片  Python Tkinter模块详解(后续持续补充)_第23张图片

除了向下拉菜单中添加自带选项之外,还可以添加单选、复选按钮。自带特殊函数如下:

函数

含义

menu.add_cascade

添加子选项

menu.add_command 

添加命令(label参数为显示内容)

menu.add_separator

添加分隔线

menu.add_checkbutton

添加确认按钮

delete

删除

该按钮可以在窗体其他位置创建菜单按钮,而不仅仅在顶级菜单中。创建方法与Menu的顶级菜单类似,代替了导航栏的位置。

示例:

from tkinter import *

root = Tk()

def callback():
    print("~被调用了~")

mb = Menubutton(root, text="点我", relief=RAISED)
mb.pack()

filemenu = Menu(mb, tearoff=False)
filemenu.add_checkbutton(label="打开", command=callback, selectcolor="yellow")
filemenu.add_command(label="保存", command=callback)
filemenu.add_separator()
filemenu.add_command(label="退出", command=root.quit)
mb.config(menu = filemenu)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第24张图片

OptionMenu 选项菜单

该组件是下拉菜单的改版,同样弥补了Listbox无法实现下拉列表框的缺陷。创建时需要创建一个Variable类变量,用于记录用户的选择。

示例:

from tkinter import *

root = Tk()

variable = StringVar()
variable.set("one")

w = OptionMenu(root, variable, "one", "two", "three")
w.pack()

mainloop()
print(variable.get())

运行如下:

Python Tkinter模块详解(后续持续补充)_第25张图片

若要获取用户的选择,对变量使用get()方法即可

Message 消息组件

该组件是Label的变体,用于显示多行文本,可以自动换行,并调整文本的尺寸使其适应给定的尺寸

示例:

from tkinter import *
root = Tk()
w1 = Message(root, text="下面插播一条新闻", width=100)
w1.pack()
w2 = Message(root, text="这条新闻超级的长长长长长长长长长长", width=100)
w2.pack()
mainloop()

Spinbox 组件

该组件是TK8.4新增的组件,算是Entry的变体,类似于Scale与Entry组件的结合,使用时有点像Excel的数据有效性,用于从一些固定的值中选取一个。

Spinbox的用法与Entry非常相似,主要区别是Spinbox可以通过范围或者元组指定用户输入的内容

示例:创建一个男女信息框

from tkinter import *

root = Tk()

sb1=Spinbox(root,from_=0,to=1,value=("男","女"))
sb2=Spinbox(root,value=("男","女"))
sb1.pack()
sb2.pack()
mainloop()

运行如下:

若同时指定(from_,to)和value参数,如:

sb1=Spinbox(root,from_=0,to=1,value=("男","女"))

则value参数指定的范围会覆盖(from_,to)指定的范围

PanedWindow 组件

是TK8.4新增的组件,是一个空间管理器。与Frame类似,都是为组件提供一个框架,不过该组件允许用户调整程序的空间范围。

示例:创建一个PanedWindow组件,将空间分为两部分

from tkinter import *

m = PanedWindow(orient=VERTICAL)
m.pack(fill=BOTH, expand=1)
top = Label(m, text="top pane")
m.add(top)
bottom = Label(m, text="bottom pane")
m.add(bottom)

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第26张图片

分割线默认是不显示的。可以设置sashrelief参数设置为SUNKEN,将showhandle参数设置为True则可以添加一个手柄(handle)

示例:添加横竖两个iPanedWindow组件,分隔空间为3部分,使分割线显示并添加手柄

from tkinter import *

m1 = PanedWindow(showhandle=True, sashrelief=SUNKEN)
m1.pack(fill=BOTH, expand=1)

left = Label(m1, text="left pane")
m1.add(left)
m2 = PanedWindow(orient=VERTICAL, showhandle=True, sashrelief=SUNKEN)
m1.add(m2)

top = Label(m2, text="top pane")
m2.add(top)

bottom = Label(m2, text="bottom pane")
m2.add(bottom)

mainloop()

运行如下:分隔三部分,可以先分为两部分,再添加一条线,分隔成三部分,如图

Python Tkinter模块详解(后续持续补充)_第27张图片

Toplevel 顶级窗口

该组件类似于Frame组件,但是该组件有独立的标题栏、边框等部件,类似于弹窗,或者称子窗体。

主要用于显示额外的窗口、对话框和其他弹出窗口

示例:创建一个按钮,单击一次创建一个Toplevel 弹窗

from tkinter import *
root = Tk()
def create():
    top = Toplevel()
    top.title("示例")
    msg = Label(top, text="这是一个Toplevel")
    msg.pack()

Button(root, text="创建", command=create).pack()
mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第28张图片

若想获取和设置Toplevel的窗口属性,可以通过attributes()方法。若只设置属性名,则返回当前窗口该属性值;若设置属性名和值,则修改窗口的属性值

示例:将Toplevel的窗口设置为50%透明

from tkinter import *
root = Tk()
def create():
    top = Toplevel()
    top.title("示例")
    top.attributes("-alpha", 0.5)
    msg = Message(top, text="这是一个Toplevel")
    msg.pack()
Button(root, text="创建Toplevel", command=create).pack()
mainloop()

事件

事件绑定

事件,是执行某一操作时触发的事情。如:人饿的时候吃饭会饱,吃饭是操作,执行吃饭的操作时,饥饿感和饱腹感都在不断变化,相当于“吃饭”操作触发了“修改人的饥饿感属性和饱腹感属性”的事件。

一个Tkinter程序大部分事件都花在事件循环中(通过maxinloop()方法进入循环)。事件可以有各种来源,包括用户触发的鼠标、键盘操作和窗口管理器触发的重绘事件(绝大多数情况下都是由用户间接引起的)。

Tkinter提供一个强大的机制可以自由地处理事件:对每个组件来说,可通过bind()方法将函数或方法绑定到具体的事件上。当被处罚的事件满足该组件绑定的事件时,Tkinter就会带着事件描述去调用handler()方法。

示例:捕获键盘敲击位置

from tkinter import *

root = Tk()

def callback(event):
    print("敲击位置:", repr(event.char))

frame = Frame(root, width=200, height=200)
frame.bind("", callback)
frame.focus_set()  #使组件获得焦点
frame.pack()

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第29张图片

注:键盘事件需要组件获得焦点才能接收,故需要用focus_set()方法使组件获得焦点

根据上述示例,可以大致归纳出绑定事件的基本步骤:

  1. 创建事件触发时的操作(指定的函数或方法)
  2. 创建组件
  3. 组件.bind(事件类型,触发时的操作)
  4. 组件.focus_set()(获取焦点,若不需要获取焦点就能捕捉事件则不用这句)
  5. mainloop()

事件序列

Tkinter可以使用事件序列的机制来自定义事件,只需要用bind()方法将具体的事件序列与自定义的方法绑定即可。

事件序列以字符串的形式表示,可以表示一个或多个相关联的事件(若为多个事件,需要满足所有事件条件才会调用)。

事件序列的语法为:

  • 事件序列包含在尖括号<>中
  • type部分的内容是最重要的,用于描述普通的事件类型,如单击鼠标单击键盘等
  • modifier部分是可选的,通常用于描述组合键,如:Ctrl+C,Shift+单击
  • detail部分是可选的,通常用于描述具体的按键,如:Button-1表示鼠标左键

语法示例:

                                 表示用户单击左键

                           表示用户单击H案件

      表示用户同时单击Ctrl+Shift+H

type部分常用关键词及含义:

type部分常用关键词及含义

type关键词

含义

Activate

当组件的状态从“未激活”变为“激活”的时候触发事件

Button

当用户单击鼠标按键时触发事件。detail部分指定具体哪个按键:鼠标左键,鼠标中建,鼠标右键,滚轮上滚(Linux),滚轮下滚(Linux)。

ButtonRelease

当用户释放鼠标按键的时候触发事件。在大多数情况下,比Button更好用,因为当用户不小心按下鼠标,用户可以将鼠标移出组件再释放鼠标,从而避免不小心触发事件

Configure

当组件的尺寸发生改变的时候触发事件

Deactivate

当组建的状态从“激活”变为“未激活的时候触发事件

Destroy

当组件被小伙的时候触发事件

Enter

当鼠标指针进入组件的时候触发事件。注意:不是指用户按下回车键

Expose

当窗口或组件的某部分不再被覆盖的时候触发事件

FocusIn

当组件获得焦点的时候触发事件。用户可以用Tab键将焦点转移到该组件上(需要该组件的takefocus选项为True);也可以调用focus_set()方法使该组件获得焦点

FocusOut

当组件失去焦点的时候触发事件

KeyPress

当用户按下键盘按键的时候触发事件。detail可以指定具体的按键,例如表示当大写字母H被按下的时候触发事件。KeyPress可以简写为Key

KeyRElease

当用户释放键盘按键的时候触发事件

Leave

当鼠标指针离开组件的时候触发事件

Map

当组件被映射的时候触发事件。意思是在应用程序中显示该组件的时候触发事件,例如调用grid()方法

Motion

当鼠标在组件内移动的整个过程均触发事件

MouseWheel

当鼠标滚轮滚动的时候触发事件。目前仅支持Windows和Mac系统,Linux请参考Button

Unmap

当组件被取消映射的时候触发事件。指在应用成组中不再显示该组件的时候触发事件,例如调用grid_remove()方法

Visibility

当应用程序至少有一部分在屏幕中是可见的时候触发事件

modifier部分常用的关键词及含义

modifier部分常用的关键词及含义

关键词

含义

Alt

当按下Alt按键的时候触发事件

Any

表示任何类型的按键被按下的时候触发事件。例如表示当用户按下任何按键时触发事件

Control

当按下Ctrl按键的时候触发事件

Double

当后续两个事件被连续触发的时候触发事件。例如表示当用户双击时触发事件

Lock

当打开大写字母锁定键(CapsLock)的时候触发按键

Shift

当按下Shift按键的时候触发事件

Triple

与Double类似,当后续三个事件被连续触发的时候触发事件

 

Event对象

当Tkinter回调预先定义的函数时,将带着Event对象(作为参数)去调用。

Event对象的属性及含义:

Event对象的属性及含义

属性

含义

widget

产生该事件的组件

x, y

当前的鼠标位置坐标(相对于窗口左上角,以像素为单位)

x_root, y_root

当前的鼠标位置坐标(相对于屏幕左上角,以像素为单位)

char

按键对应的字符(键盘事件专属)

keysym

按键名(键盘事件专属)

keycode

按键码(键盘事件专属)

num

按钮数字(鼠标事件专属)

width, height

组件的新尺寸(Configure 事件专属))

type

该事件的类型

当事件为时,detail可通过设定具体的按键名keysym来达到筛选的目的。

键盘所有特殊案件的keysym和keycode:

键盘所有特殊案件的keysym和keycode

按键名(keysym)

按键码(keycode)

含义

Alt_L

64

左边的 Alt 键

Alt_R

113

右边的 Alt 键

BackSpace

22

BackSpace(退格)键

Cancel

110

break 键

Caps_Lock

66

CapsLock

Control_L

37

左边的 Ctrl 键

Control_R

109

右边的 Ctrl 键

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

90

小键盘 0

KP_1

87

小键盘 1

KP_2

88

小键盘 2

KP_3

89

小键盘 3

KP_4

83

小键盘 4

KP_5

84

小键盘 5

KP_6

85

小键盘 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

小键盘 Delete

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_Multiply

63

小键盘 *

KP_Next

89

小键盘 PaageDown

KP_Prior

81

小键盘 PageUp

KP_Right

85

小键盘 →

KP_Subtract

82

小键盘 -

KP_Up

80

小键盘 ↑

Next

105

PageDwon 键

Num_Lock

77

Num_Lock(数字锁定) 键

Pause

110

Pause(暂停) 键

Print

111

PrintScm(打印屏幕) 键

Prior

99

PAgeUP 键

Return

36

Enter(回车)键

Right

102

→ 键

Scroll_Lock

78

Scroll_Lock 键

Shift_L

50

左边的 Shift 键

Shift_R

62

右边的 Shift 键

Tab

23

Tab 键

Up

98

↑键

 

标准对话框

messagebox 消息对话框

messagebox 消息对话框样式汇总

使用函数

对话框样式

askokcancle()

Python Tkinter模块详解(后续持续补充)_第30张图片

askquestion()

Python Tkinter模块详解(后续持续补充)_第31张图片

askretrycancel()

Python Tkinter模块详解(后续持续补充)_第32张图片

askyesno()

Python Tkinter模块详解(后续持续补充)_第33张图片

showerror()

Python Tkinter模块详解(后续持续补充)_第34张图片

showinfo()

Python Tkinter模块详解(后续持续补充)_第35张图片

showwarning()

Python Tkinter模块详解(后续持续补充)_第36张图片

所有函数都有相同的参数:title、message、options

title:设置标题栏的文本内容

message设置对话框的主要文本内容,可以用’\n’来实现换行

options参数设置内容见下表

options参数设置内容

options选项

含义

default

设置默认的按钮(直接回车时相应的按钮),默认是第一个按钮

icon

指定对话框显示的图标,可以是error、INFO、QUESTION、WARNING。但是不能是自己的图标

parent

如果不指定该选项,那么对话框默认显示在根窗口上

如果想要将对话框显示在子窗口w上,设置parnet=w

关于parent需要注意的是:如果未指定parent参数,也未创建一个任何一个窗体,使用上述函数

生成messagebox时,会自动创建一个空白的Tk窗体,产生的效果与实例化Tk()相同。空白Tk窗体如下:

Python Tkinter模块详解(后续持续补充)_第37张图片

而如果parent参数设置的是Tk类下的子窗体,如Toplevel,则会创建两个空白tk窗体,一个表示Tk窗体,一个表示Toplevel窗体。运行如下:

Python Tkinter模块详解(后续持续补充)_第38张图片

窗体间的结构大致如下:

Python Tkinter模块详解(后续持续补充)_第39张图片

若关闭Toplevel,则会同时关闭messagebox;若关闭Tk,则会将Toplevel、messagebox一同关闭,因为他们都是基于Tk创建的子窗体。

但是,当直接关闭Tk时,会出现AttributeError: 'NoneType' object has no attribute 'tk'异常;关闭Toplevel再关闭Tk或从messagebox开始从上往下关闭,则不会出现该异常。

返回值

askokcancel()、askretrycancel()和askyesno()返回bool类型值:

  1. 返回True表示用户单击了“确定“或”是“按钮
  2. 返回False表示用户单击了“取消“或”否:按钮

askquestion()返回yes或no字符串表示用户单击了“是”或:否“按钮
showerror(),showinfo()或showwarning()返回ok表示用户按下了“是“按钮

fieldialog 文件对话框

示例:打开文件,并获取路径

from tkinter import *
import tkinter.filedialog
root = Tk()

def callback():
    fileName = tkinter.filedialog.askopenfilename()
    print(fileName)

Button(root, text="打开文件", command=callback).pack()

mainloop()

运行如下:

Python Tkinter模块详解(后续持续补充)_第40张图片

注:若没有import tkinter.filedialog 语句,则会出现错误:NameError: name 'filedialog' is not defined

filedialog模块提供以下函数

filedialog 内置函数

函数

含义

askopenfile()

生成打开单个文件的对话框,返回所选择文件的文件流

askopenfiles()

生成打开多个文件的对话框,返回多个所选择文件的文件流组成的列表

askopenfilename()

生成打开单个文件的对话框,返回所选择文件的文件路径

askopenfilenames()

生成打开多个文件的对话框,返回多个所选择文件的文件路径组成的元组

asksaveasfile()

生成保

运行如下:

Python Tkinter模块详解(后续持续补充)_第41张图片

注:若没有import tkinter.filedialog 语句,则会出现错误:NameError: name 'filedialog' is not defined

filedialog模块提供以下函数:

函数

含义

askopenfile()

生成打开单个文件的对话框,返回所选择文件的文件流

askopenfiles()

生成打开多个文件的对话框,返回多个所选择文件的文件流组成的列表

askopenfilename()

生成打开单个文件的对话框,返回所选择文件的文件路径

askopenfilenames()

生成打开多个文件的对话框,返回多个所选择文件的文件路径组成的元组

asksaveasfile()

生成保存文件的对话框,返回所选择文件的文件输出流

asksaveasfilename()

生成保存文件的对话框,返回所选择文件的文件路径

askdirectory()

生成打开目录的对话框

 

两个函数可供设置的参数是一样的,参数如下

参数

含义

defaultextension

指定文件的后缀,例如defaultextension=“.jpg“,当用户输入一个文件名是,会自动添加.jpg后缀

注:若输入的文件名包含后缀,则该选项不生效

filetypes

指定筛选文件类型的下拉菜单选项,该选项的值是由2元组构成的列表。每个2元组由(类型名,后缀名)构成,如:filetypes=[(“PNG”,”.png”),(“JPG”,”.jpg”)]

initialdir

指定打开/保存文件的默认路径,默认路径是当前文件夹

initialfile

指定所选择的文件

parent

如果不指定该选项,那么对话框默认显示在根窗口上

如果想要将对话框显示在子窗口w上,设置parent=w

title

指定文件对话框的标题栏文本

multiple

指定是否允许多选

对于打开目录的对话框,还额外支持一个 mustexist 选项,该选项指定是否只允许打开己存在的目录

返回值

  1. 如果用户选择了一个文件,那么返回值是该文件的完整路径
  2. 如果用户单击了“取消“按钮,那么返回值是空字符串

的对话框,返回所选择文件的文件输出流

asksaveasfilename()

生成保存文件的对话框,返回所选择文件的文件路径

askdirectory()

生成打开目录的对话框

这些函数可供设置的参数基本上是一样的,参数如下

filedialog 参数汇总

参数

含义

defaultextension

指定文件的后缀,例如defaultextension=“.jpg“,当用户输入一个文件名是,会自动添加.jpg后缀

注:若输入的文件名包含后缀,则该选项不生效

filetypes

指定筛选文件类型的下拉菜单选项,该选项的值是由2元组构成的列表。每个2元组由(类型名,后缀名)构成,如:filetypes=[(“PNG”,”.png”),(“JPG”,”.jpg”)]

initialdir

指定打开/保存文件的默认路径,默认路径是当前文件夹

initialfile

指定所选择的文件

parent

如果不指定该选项,那么对话框默认显示在根窗口上

如果想要将对话框显示在子窗口w上,设置parent=w

title

指定文件对话框的标题栏文本

multiple

指定是否允许多选

注:对于打开目录的对话框,还额外支持一个 mustexist 选项,该选项指定是否只允许打开己存在的目录

返回值

  • 如果用户选择了一个文件,那么返回值是该文件的完整路径
  • 如果用户单击了“取消“按钮,那么返回值是空字符串

你可能感兴趣的:(Python学习笔记)