此教程是我的自学笔记,每个部分我都进行科学的编排,其中较为难理解的是 Tk 概念,布局方式。如果你阅读后还是无法理解,我先说一声抱歉。你可以将疑问汇总,然后通过客服或私信发送给我,我看到后会及时回复,并更新在线文档。此教程不能详尽的包含所有Tk知识点,光官方文档就超过百页,这是无法避免的事实,因此你可以在需要的时候查阅官方文档获取详细信息,或者通过浏览器获取别人的教程。祝你学的愉快!
公众号:PASSLINK 小红书:锦沐Python
简介
tkinter 是 Python 自带的内置依赖包,简称 Tk , 是 Python的标准接口 Tcl/Tk GUI 工具包,虽然他很古老,但作为入门GUI编程是个不错的选择。Tk 在大多数平台上都可以使用,包括 Unix,macOS,以及 Windows 系统。
一个简单的示例:
from tkinter import *
from tkinter import ttk
root = Tk()
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
root.mainloop()
你可以在python里运行该代码,运行成功会弹出一个窗口:
我们可以观察到窗口标题,最小化,最大化,关闭按钮。在窗体内显示有文字和一个按钮,并且他们是并排放置。现在你可以回头看示例代码,你可能已经猜到代码的大致含义了:
# 导入 tkinter
from tkinter import *
from tkinter import ttk
# 创建主窗口实例
root = Tk()
# 创建一个容器放置到主窗口内部
frm = ttk.Frame(root, padding=10)
# 配置该容器的布局方式为 栅格 布局
frm.grid()
# 创建文字标签,并放置到 第1行 第1列 的位置
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
# 创建按钮,并放置到 第1行 第2列 的位置
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
# 开启主窗口循环,显示窗口
root.mainloop()
重要的 Tk 概念
在写代码之前,我们首先应当具体了解一下 Tk 的 轮廓,也就是它的设计结构。
部件(Widget)
Tkinter 用户界面是由各个部件组成的。每个窗口小部件都表示为一个 Python 对象,他们都继承 Widget 类,每次我们需要一个部件就要创建对应的部件 类实例。部件就是零件的意思,就好比儿童玩具里的积木,有不同的形状结构,不同的功能,将它们有序的整合到一起就形成了一个完整的 Tk 程序。
下表包含了常见的部件类名,以及含义,你可以在需要特定功能的时候进行查询,也可以将部件名称作为关键词,在官方文档中查询更详细的信息:
部件名称 | 含义 |
Label | 标签,用于显示文本或图像。 |
Button | 按钮,用于触发操作或事件,绑定回调函数。 |
Entry | 单行文本输入框。 |
Text | 多行文本输入框。 |
Frame | 框架容器,用于组织和布局其他部件。 |
Canvas | 画布,用于绘制图形和复杂布局。 |
Checkbutton | 复选框,用于选择多个选项中的一个或多个。 |
Radiobutton | 单选按钮,用于从多个选项中选择一个。 |
Scale | 滑动条,用于从一定范围内选择数值。 |
Listbox | 列表框,一个可选项目列表。 |
Scrollbar | 滚动条,用于滚动其他部件中的内容,需要绑定其他部件。 |
Menu | 菜单,应用程序里的选项,就和菜单栏一样。 |
Menubutton | 菜单按钮,用于创建可弹出菜单的按钮。 |
Toplevel | 顶层窗口,用于创建独立的顶级窗口,自定义提示框。 |
Message | 消息框,用于显示多行文本消息,与 Label 部件类似。 |
Spinbox | 数字框,允许用户从预定义的一系列值中选择一个数值。 |
PanedWindow | 分隔窗口,可以水平或垂直地分隔窗口区域。 |
LabelFrame | 标签框架,带有标题的框架,用于组织和标记相关的部件。 |
Notebook | 多页框架容器,用于创建多页标签页布局,可以用于不同页面的切换。 |
Progressbar | 进度条,用于显示任务的完成进度。 |
Separator | 分隔符,用于在用户界面中创建分隔线。 |
下图是 tkinter 的源码,我们把代码收缩起来后,可以明显观察到,所有部件都继承 Widget ,也就是说无论是按钮,标签,还是文本框,他们都有相同的父类 Widget,他们都含有的 Widget 属性和方法。
我们接着看看父类 Widget 是什么,Widget 里啥也没有,但是继承了 BaseWidget 以及Pack, Place, Grid三个类。我们看到注释里的关键词 positioned(定位:把部件放在窗口的某个位置),说的就是 Pack, Place, Grid 三中不同的方式控制部件在窗口里的布局位置。然后我们看 BaseWidget 类除了几个函数,还继承了 Misc(其他杂项)。
追踪到 Misc 类后,我们终于到顶端了,他不再继承其他自定义类了,并且注释告诉我们,该类的功能就是定义基础方法给子部件使用。
部件(Widget)层次结构
部件按层次结构进行组合或者排列,根据最开始代码示例,我们可以看到标签和按钮包含在一个框架(Frame)内,而框架又包含在根窗口(Tk)中。创建每个子 widget 时,其父 widget 将作为第一个参数传递给组件构造函数,也就是实例化时传递给类的第一个参数,当然你也可以直接用参数名传递:master=父部件。一些部件(Widget) 是可以进行嵌套的,或者并列的,比如Frame,LabelFrame等,一般为了好理解我们叫它容器。你可以抽象的将 父容器看作一个袋子,子容器装在袋子里面被父容器统一管理。父容器不是唯一的,只有根容器是唯一的 Tk() 。父容器是相对的说法,就像爷爷,爸爸,儿子,孙子之间的关系,嵌套就是父子之间,并列就是兄弟之间。
配置选项
每个部件有单独的配置选项,可修改其外观(大小,颜色,文字等)和行为(点击事件,内容变更等),例如在标签或按钮并列,各自有不同的文字内容,位置,外形,其中按钮可以被点击并触发某个函数执行。
属性 | 描述 |
Dimension | 控件大小; |
Color | 控件颜色; |
Font | 控件字体; |
Anchor | 锚点; |
Relief | 控件样式; |
Bitmap | 位图; |
Cursor | 光标; |
布局管理
创建部件时,它们不会自动添加到用户界面。布局管理器可以控制它们在用户界面中的位置,Tk 提供了三种方式 Pack, Place, Grid ,这三种方式都被部件继承了,可以像对象的函数一样直接调用它们。值得注意的是,并列(兄弟)关系的组件必须使用相同的部件方式。
- 使用
pack
布局管理器当你需要简单的垂直或水平排列,并且不需要精确的控制组件的位置。(推荐使用,缩放窗口时自动调整位置) - 使用
grid
布局管理器当你需要将组件放置在一个表格中,并且希望通过行和列来控制组件的位置和大小。 - 使用
place
布局管理器当你需要非常精确地控制组件的位置和大小,或者需要组件有重叠的情况。(通常只有在局部容器使用,用于调整一些细节)
事件循环
Tkinter 只有在事件循环时,才会对用户输入、程序变化做出反应,甚至刷新显示屏。如果你的程序没有运行事件循环,你的用户界面就不会更新。
看到循环,很多人都会疑惑,一个窗口和循环什么关系。我们可以先了解一下屏幕的大致原理吧:我相信你应该听过频率吧,也听过刷新率吧,你可以在电脑或手机的屏幕参数里看到它。打开电脑设置查看:
我们可以清楚的知道屏幕刷新率是60Hz了,60Hz是什么概念呢,一秒中内播放60张图片,每张图片存留 1/60 秒,也就是0.016667 秒。由于人眼捕捉画面的速度是有下限的,因此我们看到高频率播放的图片非常流畅且丝滑,如果每张图片都有变化那么他就变成明显的视频了。我想告诉你的是,我们看到的屏幕内容其实都是图片连续播放构成的,你觉得丝滑是因为播放图片的速度非常快,你感觉不到卡顿而已。
那和循环有什么关系呢?我的观点:一个机器要不停的运作,底层一定至少有一个循环。你可以简单的把每个事件看作一个循环内的函数,每个状态看作循环内的变量,当我们触发事件时,会改变某些变量值,从而改变他的状态。
就像屏幕上的鼠标,你不操作电脑,它就一直在那(状态),你只要移动鼠标激发移动事件(函数),改变了内部的鼠标位置参数(变量),鼠标就在下一次循环里更新位置(新的状态)。由于他非常快,所有我们不能察觉到它本质上播放了十几张或上百张图片。换到我们的 Tk 窗口情景, 你可以类比你的WPS编辑器或者Word等软件,你输入文字的容器其实就是一个Text部件,每次改变文字内容,他会迅速响应屏幕刷新画面,从而将你输入的文字展现出来。你现在应该理解为什么说:程序没有运行事件循环,你的用户界面就不会更新了吧,所以该程序其实就是一个循环。
在源码里,你可以在Misc类里找到一个while循环:
Tk 基础
了解了Tk基本概念后,我们可以开始学习使用他了,在这个过程中你的重点应当是理解部件是如何构成一个有规则的窗口视图,也就是如何设计窗口布局。你可以把部件当作不同的积木,将他们混和搭配并排列出有规则的视图,每个积木有不同的职责。你主要关注的问题是:1. 该部件最大的特点是什么?2. 该部件在什么场景下使用?3. 该部件有哪些基本的配置?
窗口坐标系
在学习部件之前,我们先了解一下窗口的坐标系,我们讨论 2D 空间。两个坐标轴为 X轴 和 Y轴,原点为(0,0)。
规则:所有窗口的原点在左上角,包括你现在看到的屏幕内容也是一个窗口。以左上角为起点水平向右为 X 轴,以原点为起点垂直向下为 Y 轴。此时你的脑海应当保留下面的图,你应当知道每个窗口都有独立的坐标系:
主窗口 Tk
所有部件都要统一管理起来,就要把他们装到一个容器里。主窗口作为最顶层的父类,它可以包含所有部件,没有主窗口就不会显示任何内容。所以,我们一开始就要创建一个主窗口,作为根容器,用来装载其他部件。看代码前,我们先来观察创建后的窗口。(为什么先看视图?因为你学完Tk基础后,要进行开发程序,最先做的应当是把设计图画出来,然后再进行分析与编码。)
我们可以看到 Tk 主窗口包含了标题栏,以及一块红色的区域,细节上,标题栏有自定义的图标,自定义的标题,以及右侧的常见按钮(程序默认的)。红色区域就是根容器,你创建的部件都将包含在红色区域内。
# -*- coding: utf-8 -*-
from tkinter import *
import ctypes
# 在Windows操作系统中,AppUserModelID 是一种标识符,用于唯一标识应用程序。这个标识符可以影响到应用程序在任务栏、开始菜单和其他位置的显示方式和分组方式。这条代码可以让你的图标显示在状态栏,也就是你桌面最下面的图标栏。
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID('passlink_tk')
if __name__ == "__main__":
# 创建主窗口
main_window = Tk()
# 设置窗口透明度
main_window.wm_attributes('-alpha', 1)
# 设置了主窗口的宽度为600像素,高度为400像素,并将窗口的左上角位置定位在屏幕上的坐标(x:200, y:200)处
main_window.geometry("600x400+200+200")
# 自定义标题
main_window.title("锦沐的小程序")
# 自定义容器背景颜色
main_window.configure(background="red")
# 自定义程序图标
main_window.iconbitmap("./icon.ico")
# 设置窗口的最小宽度和最小高度
main_window.minsize(500, 300)
# 设置窗口的最大宽度和最大高度
main_window.maxsize(700, 500)
# 启动程序
main_window.mainloop()
Frame :框架
用于组织和布局其他部件,他是一个容器,可以容纳任何部件,一般我们用它划分窗口功能区域,对窗口进行主体布局。我们在设计的时候就会考虑到编码是将相似的功能分配到一个 Frame 部件里进行统一管理。
# 创建一个黄色背景的长 400 像素的正方形,使用 pack 布局
frame = Frame(master=main_window, bg="yellow", width=400, height=400)
# 固定大小,禁止 pack 自动调整大小
frame.pack_propagate(False)
# 一定要配置布局方法,否则部件不显示,我们使用 pack() 方法进行默认布局
frame.pack()
Label :标签
用于显示文本或图像,将一些文字或者图片显示到窗口里。
if __name__ == "__main__":
main_window = Tk()
# 设置了主窗口的宽度为600像素,高度为400像素,并将窗口的左上角位置定位在屏幕上的坐标(200, 200)处
# 设置窗口透明度
main_window.wm_attributes('-alpha', 1)
main_window.geometry("600x400+200+200")
main_window.title("锦沐的小程序")
main_window.configure(background="#5AA7EA")
main_window.iconbitmap("./icon.ico")
# 设置窗口的最小宽度和最小高度
main_window.minsize(500, 300)
# 设置窗口的最大宽度和最大高度
main_window.maxsize(900, 800)
# 创建 Label 部件并将其放置在 Frame 内
label1 = Label(master=frame, text="Hello1")
label1.pack(anchor="center")
label2 = Label(master=frame, text="Hello2", bg="#5DE2E7")
label2.pack()
label3 = Label(master=frame, text="Hello3", bg="#5DE2E7", fg="red")
label3.pack()
label4 = Label(master=frame, text="Hello4", bg="#5DE2E7", fg="red", font=("Arial", 20))
label4.pack()
main_window.mainloop()
参数 | 含义 |
| 父容器,即控件所属的窗口或框架 |
| 显示在 Label 上的文本内容 |
| 文本内容的左右和上下内边距(像素)整数 |
| 背景颜色,支持16进制颜色 |
| 前景颜色,即文本颜色 |
| 字体属性,包括字体名称和字体大小 |
显示图像:
# 加载图片
img = PhotoImage(file="icon.png")
# 创建Label来显示图片
label_img = Label(master=frame, image=img)
label_img.pack(expand=True)
三种布局方式
注意:并列(兄弟)部件布局方式必须相同
Pack 布局
pack 是最常用使用的, 它可以根据窗口缩放进行自动布局。刚才我们使用了默认的 pack 布局,没有添加任何参数,现在我们添加常见参数进行观察。
参数 | 描述 |
| 控制部件在父容器中的放置方向。 "left", "right", "top", "bottom" |
| 指定部件是否填充可用空间。 "none", "x", "y", "both" |
| 指定部件是否可以扩展以填充额外空间。True | False |
| 指定部件在其分配的空间中的对齐方式。"nw", "n", "ne", "w", "center", "e", "sw", "s", "se" |
| 指定部件相对于其周围的外部填充(水平方向)。 像素 |
| 指定部件相对于其周围的外部填充(垂直方向)。 像素 |
| 指定部件相对于其内部内容的内部填充(水平方向)。 像素 |
| 指定部件相对于其内部内容的内部填充(垂直方向)。 像素 |
| 将部件放到传入的部件前面 |
| 将部件放到传入的部件后面 |
label5 = Label(master=frame, text="Hello5")
label5.pack(padx=(100, 20))
label6 = Label(master=frame, text="Hello6")
label6.pack(pady=(20, 50))
label7 = Label(master=frame, text="Hello7")
label7.pack(padx=50)
label8 = Label(master=frame, text="Hello8")
label8.pack(pady=20)
label9 = Label(master=frame, text="Hello9")
label9.pack(ipadx=20)
label10 = Label(master=frame, text="Hello10")
label10.pack(ipady=20)
label11 = Label(master=frame, text="Hello11")
label11.pack(side="right")
label12 = Label(master=frame, text="Hello12")
label12.pack(side="left")
label13 = Label(master=frame, text="Hello13")
label13.pack(fill="both")
label14 = Label(master=frame, text="Hello14")
label14.pack(fill="x")
label15 = Label(master=frame, text="Hello15")
label15.pack(expand=True)
label16 = Label(master=frame, text="Hello16")
label16.pack(anchor="se")
label17 = Label(master=frame, text="Hello17")
label17.pack(anchor="w")
对于 pdx,pdy,ipdx,ipdy 的解释:
pd 是 padding 的缩写,ipd是部件内部 padding 的意思。当 pdx 传入一个元组,表示(左边外边距,右边外边距),当 pdy 传入一个元组,表示(上边外边距,下边外边距);当 pdx或pdy 传入一个整数表示左右或上下都一样。ipdx 或 ipdy 只能传递一个整数。
before 与 after 参数是部件类型,将该部件放到传入部件的前面或者后面。
label17 = Label(master=frame, text="Hello17")
label17.pack(anchor="w")
label18 = Label(master=frame, text="Hello18")
label18.pack(before=label17)
label19 = Label(master=frame, text="Hello19")
label19.pack(after=label18)
Grid 布局
栅格布局,将部件当作网格单元进行布局。如果要一个部件占据多行或者多列,前提是占据的行或列存在其他部件,且位置不冲突,使用 sticky 可以将网格充满。
参数 | 描述 |
| 放置部件的网格行数。 从 0 开始 |
| 放置部件的网格列数。 从 0 开始 |
| 部件占据的行数。 |
| 部件占据的列数。 |
| 部件在其分配的网格空间内的对齐方式。 "nsew" |
| 外部填充,相对于部件周围的外部空间。 |
| 内部填充,相对于部件内部内容的空间。 |
label = Label(master=frame, text="0行0列")
label.grid(row=0, column=0, pady=5, padx=5)
label = Label(master=frame, text="0行1列")
label.grid(row=0, column=1, pady=5, padx=5)
label = Label(master=frame, text="1行0列")
label.grid(row=1, column=0, pady=5, padx=5)
label = Label(master=frame, text="1行1列")
label.grid(row=1, column=1, pady=5, padx=5)
label = Label(master=frame, text="2行0列")
label.grid(row=2, rowspan=2, column=0, pady=5, padx=5, sticky="nsew")
label = Label(master=frame, text="3行1列")
label.grid(row=3, column=1, pady=5, padx=5)
label = Label(master=frame, text="2行1列")
label.grid(row=2, column=1, columnspan=3, pady=5, padx=5, sticky="nsew")
label = Label(master=frame, text="3行2列")
label.grid(row=3, column=2, pady=5, padx=5)
label = Label(master=frame, text="3行3列")
label.grid(row=3, column=3, pady=5, padx=5)
label = Label(master=frame, text="4行0列")
label.grid(row=4, column=0, pady=5, padx=5)
label = Label(master=frame, text="4行1列")
label.grid(row=4, column=1, pady=5, padx=5)
Place 布局
一般要精确定位部件时才使用 place。
参数名 | 描述 |
| 指定部件左上角相对于其父容器(通常是窗口或帧 Frame)的 x 和 y 坐标位置。 |
| 指定部件左上角相对于父容器的相对位置,取值范围为 0.0 到 1.0。例如, |
| 控制部件在其指定位置的对齐方式,总共八个方向,东南西北,东北,东南,西南,西北。 |
| 指定部件的宽度和高度。可以使用具体的像素值或者字符 |
| 指定部件的相对宽度和高度,取值范围为 0.0 到 1.0。例如, |
| 设置边界模式,可以是 |
label = Label(master=frame, text="100-100")
label.place(x=100, y=100)
label = Label(master=frame, text="150-150")
label.place(x=150, y= 150)
label = Label(master=frame, text="0.5-0.5")
label.place(relx=0.5, rely=0.5)
label = Label(master=frame, text="0.3-0.7")
label.place(relx=0.3, rely=0.7)
label = Label(master=frame, text="100% - 40%")
label.place(x=220, y=10, width="100p", height="40p")
label = Label(master=frame, text="50px-80px")
label.place(x=220, y=80, height=50, width=80)
label = Label(master=frame, text="0.3-0.2")
label.place(x=200, y=230, relwidth=0.3, relheight=0.2)
对于 anchor 参数解释:
anchor 意思为锚点,是用来给部件进行定位的,相对于父容器进行定位,总共八个方向,东南西北,东北,东南,西南,西北。
label = Label(master=frame, text="center")
label.place(anchor="center")
label = Label(master=frame, text="n")
label.place(anchor="n")
label = Label(master=frame, text="ne")
label.place(anchor="ne")
label = Label(master=frame, text="e")
label.place(anchor="e")
label = Label(master=frame, text="se")
label.place(anchor="se")
label = Label(master=frame, text="s")
label.place(anchor="s")
label = Label(master=frame, text="sw")
label.place(anchor="sw")
label.place(anchor="w")
label = Label(master=frame, text="nw")
label.place(anchor="nw")
部件
下面的内容包含了所有部件信息,我为每个部件都分配了 运行截图,常用参数表格,参考代码。学习的时候,你应当先观察图片,然后简单了解各参数含义,最后再将代码与图片内容对应起来。参数表格完整版可以参考配套官方文档查看,参考代码省略了主窗口代码。
对于大部分部件,你可能要解决这些问题:1. 显示什么内容 2.显示什么样式 3.显示到哪里
Frame:矩形区域,用于分组和组织其他部件
Label: 显示文本或图像的部件
LabelFrame:有标题的框架
包含边框和标题的框架部件,一般我们可以将它作为布局容器,用于区分不同的功能区。
参数 | 描述 |
master | 父容器 |
bd | 边框宽度(以像素为单位),默认为2像素。 |
bg | 背景色。 |
cursor | 当鼠标位于 LabelFrame 上方时的光标样式。默认是标准箭头。 |
font | 文本字体。 |
foreground | 前景色,即文本颜色。 |
labelanchor | 标签位置锚点。可以是 "n", "e", "s", "w", "center" 中的一个。默认为 "nw"(西北)。 |
relief | 边框样式。可以是 "flat", "raised", "sunken", "solid", "ridge", "groove" 中的一个。默认为 "groove"。 |
text | LabelFrame 的标题文本。 |
width | LabelFrame 的宽度。如果没有指定,它将自适应内容。 |
height | LabelFrame 的高度。如果没有指定,它将自适应内容。 |
l_frame = LabelFrame(master=main_window, text="LabelFrame", width=100, height=50)
l_frame.pack()
l_frame = LabelFrame(master=main_window, text="LabelFrame", width=100, height=50, bg="#8B795E")
l_frame.pack()
l_frame = LabelFrame(master=main_window, text="LabelFrame", width=100, height=50, bd=5)
l_frame.pack()
l_frame = LabelFrame(master=main_window, text="LabelFrame", width=100, height=50, cursor="heart")
l_frame.pack()
l_frame = LabelFrame(master=main_window, text="LabelFrame", width=100, height=50, labelanchor="e")
l_frame.pack()
l_frame = LabelFrame(master=main_window, text="LabelFrame", width=100, height=50, relief="raised")
l_frame.pack()
Button : 按钮
可点击的按钮,用于触发命令或动作,需要连接自定义的回调函数。
参数 | 描述 |
master | 父容器 |
activebackground | 鼠标指针悬停在按钮上方时的背景色。 |
activeforeground | 鼠标指针悬停在按钮上方时的前景色,即文本颜色。 |
bd | 边框宽度(以像素为单位)。默认为2像素。 |
bg | 背景色。 |
command | 点击按钮时调用的函数或方法。 |
cursor | 当鼠标位于按钮上方时的光标样式。默认是标准箭头。 |
font | 文本字体。 |
fg | 前景色,即文本颜色。 |
height | 按钮的高度。默认值通常是 1,即单行文本高度。 |
highlightbackground | 按钮失去焦点时的背景色。 |
highlightcolor | 按钮获得焦点时的颜色。 |
image | 按钮上显示的图像。 |
justify | 多行文本在按钮上的对齐方式。可以是 "left", "right", "center" 中的一个。默认为 "center"。 |
padx | 水平填充(按钮文本与按钮边框的距离)。默认是 1 像素。 |
pady | 垂直填充(按钮文本与按钮边框的距离)。默认是 1 像素。 |
relief | 边框样式。可以是 "flat", "raised", "sunken", "solid", "ridge", "groove" 中的一个。默认为 "flat"。 |
state | 按钮的状态。可以是 "normal"(正常状态,可点击)、"disabled"(禁用状态)、"active"(激活状态,通常表示鼠标悬停)。默认为 "normal"。 |
text | 按钮上显示的文本。 |
textvariable | 与按钮文本关联的变量。可以是一个 StringVar() 对象。 |
underline | 指定按钮文本中哪个字符下划线(从0开始)。默认为 -1,表示没有下划线。 |
width | 按钮的宽度。如果没有指定,它将自适应内容。 |
self.flash() 函数 | 当highlightbackground,highlightcolor 配置至少一个时,闪烁1秒 |
self.invoke() 函数 | 激发 command 回调函数 |
button = Button(master=main_window, text="Button", activebackground="#7A67EE", activeforeground="#EE00EE")
button.pack()
button = Button(master=main_window, text="Button", highlightbackground="#7A67EE", highlightcolor="#EE00EE")
button.pack()
img = PhotoImage(file="icon.png")
button = Button(master=main_window, text="Button", image=img)
button.pack()
button = Button(master=main_window, text="Button", justify="right")
button.pack()
button = Button(master=main_window, text="Button", relief="sunken")
button.pack()
count = 0
def button_click():
global count
count += 1
return count
# 不会改变文本
button = Button(master=main_window, text=f"点击了{count}次", command=button_click)
button.pack()
intValue = IntVar()
def button2_click():
global strValue
intValue.set(intValue.get() + 1)
return intValue
# 改变文本
button = Button(master=main_window, textvariable=intValue, command=button2_click)
button.pack()
button = Button(master=main_window, text="Button" , command=button_click,state="disabled")
button.pack()
button = Button(master=main_window, text="Button" , underline=2)
button.pack()
def flash():
button.flash()
button = Button(master=main_window, text="Button", activebackground="red", command=flash)
button.pack()
button.flash()
Entry: 单行文本输入框
单行文本输入部件,用于用户输入,比如用户名,密码,邮箱等。
参数 | 描述 |
master | 父容器,即Entry将被放置在其中的主窗口或框架。 |
bd | 边框宽度(以像素为单位)。默认是2像素。 |
bg | 背景色。 |
cursor | 当鼠标位于Entry上方时的光标样式。默认是标准箭头。 |
exportselection | 控制是否将当前选择内容导出到其他应用程序。默认为True。 |
font | 文本字体。 |
fg | 前景色,即文本颜色。 |
highlightbackground | Entry部件失去焦点时的背景色。 |
highlightcolor | Entry部件获得焦点时的颜色。 |
justify | 文本在Entry中的对齐方式。可以是 "left", "right", "center" 中的一个。默认为 "left"。 |
relief | 边框样式。可以是 "flat", "raised", "sunken", "solid", "ridge", "groove" 中的一个。默认为 "flat"。 |
selectbackground | 选中文本时的背景色。默认为系统特定的颜色。 |
selectforeground | 选中文本时的前景色。默认为系统特定的颜色。 |
show | 用于显示的字符,例如密码字段中的"*"。 |
state | Entry部件的状态。可以是 "normal"(正常状态,可编辑)、"readonly"(只读状态)、"disabled"(禁用状态)。默认为 "normal"。 |
textvariable | 与Entry部件关联的变量。可以是一个StringVar()对象。 |
width | Entry部件的宽度,以字符数计。 |
entry = Entry(master=main_window, show="***")
entry.pack()
entry = Entry(master=main_window, state="disabled")
entry.pack()
value = IntVar()
entry = Entry(master=main_window, textvariable=value)
entry.pack()
value.set(10)
entry = Entry(master=main_window, cursor="man")
entry.pack()
Text:多行文本
多行文本编辑和显示部件,多用于长文本编辑,比如长篇文章,评论等。
参数 | 描述 |
master | 父容器 |
bd | 边框宽度(以像素为单位)。默认是2像素。 |
bg | 背景色。 |
cursor | 当鼠标位于Text上方时的光标样式。默认是标准箭头。 |
exportselection | 控制是否将当前选择内容导出到其他应用程序。默认为True。 |
font | 文本字体。 |
fg | 前景色,即文本颜色。 |
height | Text部件的高度,以行数计。 |
highlightbackground | Text部件失去焦点时的背景色。 |
highlightcolor | Text部件获得焦点时的颜色。 |
insertbackground | 光标插入点的背景色。 |
insertwidth | 光标插入点的宽度(以像素为单位)。默认为1像素。 |
relief | 边框样式。可以是 "flat", "raised", "sunken", "solid", "ridge", "groove" 中的一个。默认为 "flat"。 |
selectbackground | 选中文本时的背景色。默认为系统特定的颜色。 |
selectforeground | 选中文本时的前景色。默认为系统特定的颜色。 |
state | Text部件的状态。可以是 "normal"(正常状态,可编辑)、"disabled"(禁用状态)。默认为 "normal"。 |
width | Text部件的宽度,以字符数计。 |
wrap | 文本换行的方式。可以是 "none"(不换行)、"char"(按字符换行)、"word"(按单词换行)。默认为 "char"。 |
xscrollcommand | 用于与水平滚动条关联的回调函数。 |
yscrollcommand | 用于与垂直滚动条关联的回调函数。 |
text = Text(master=main_window, state="disabled", height=5)
text.pack()
text = Text(master=main_window, wrap="word", height=5)
text.pack()
text = Text(master=main_window, exportselection=False, height=5)
text.pack()
text = Text(master=main_window, selectforeground="red", selectbackground="blue", height=5)
text.pack()
Listbox:列表容器
显示项目列表的部件,有多选单选模式,类似通讯录列表或短信列表。
参数 | 描述 |
master | 父容器 |
activestyle | 激活(选中)项目时的样式。可以是 "none", "dotbox", "underline" 中的一个。默认为 "dotbox"。 |
bg | 背景色。 |
bd | 边框宽度(以像素为单位)。默认是2像素。 |
cursor | 当鼠标位于Listbox上方时的光标样式。默认是标准箭头。 |
exportselection | 控制是否将当前选择内容导出到其他应用程序。默认为True。 |
font | 文本字体。 |
fg | 前景色,即文本颜色。 |
height | Listbox部件的高度,以显示的项目数计。 |
highlightbackground | Listbox部件失去焦点时的背景色。 |
highlightcolor | Listbox部件获得焦点时的颜色。 |
relief | 边框样式。可以是 "flat", "raised", "sunken", "solid", "ridge", "groove" 中的一个。默认为 "flat"。 |
selectbackground | 选中项目时的背景色。默认为系统特定的颜色。 |
selectforeground | 选中项目时的前景色。默认为系统特定的颜色。 |
selectmode | 选择模式。可以是 "single"(单选)、"browse"(单选)、"multiple"(多选)、"extended"(扩展多选)。默认为 "browse"。 |
width | Listbox部件的宽度,以字符数计。 |
xscrollcommand | 用于与水平滚动条关联的回调函数。 |
yscrollcommand | 用于与垂直滚动条关联的回调函数。 |
value = StringVar()
value.set("var1 var2 var3 var1 var2 var3 var1 var2 var3 var1 var2 var3")
text = Listbox(master=main_window, listvariable= value, activestyle="underline", height=5)
text.pack()
text = Listbox(master=main_window, listvariable= value, selectforeground="red",
selectbackground="blue", height=5)
text.pack()
text = Listbox(master=main_window, listvariable= value, selectmode="multiple", height=5)
text.pack()
Radiobutton:单选框
从一组选项中选择一个选项的部件,例如男,女选项。
参数 | 描述 |
master | 父容器 |
activebackground | 当鼠标悬停在Radiobutton上方时的背景色。 |
activeforeground | 当鼠标悬停在Radiobutton上方时的前景色。 |
bg | 背景色。 |
bd | 边框宽度(以像素为单位)。默认是2像素。 |
command | 当Radiobutton被选择时调用的回调函数。 |
cursor | 当鼠标位于Radiobutton上方时的光标样式。默认是标准箭头。 |
font | 文本字体。 |
fg | 前景色,即文本颜色。 |
highlightbackground | Radiobutton部件失去焦点时的背景色。 |
highlightcolor | Radiobutton部件获得焦点时的颜色。 |
image | 替代文本标签的图像。 |
justify | 如果标签文本超过一行,控制文本的对齐方式。可以是 "left", "right", "center" 中的一个。默认为 "center"。 |
padx | 按钮的水平内边距(以像素为单位)。 |
pady | 按钮的垂直内边距(以像素为单位)。 |
relief | 边框样式。可以是 "flat", "raised", "sunken", "solid", "ridge", "groove" 中的一个。默认为 "flat"。 |
selectcolor | 选中状态时的背景色。 |
text | 按钮上显示的文本标签。 |
underline | 文本标签中下划线的位置(从0开始)。 |
value | Radiobutton的值。通常与groupname一起使用,用于区分不同的选项。 |
variable | 与Radiobutton相关联的Tkinter变量,通常是IntVar或StringVar类型的变量。 |
width | 按钮的宽度,以字符数计。 |
# 创建一个Tkinter变量来存储所选选项的值
selected_option = IntVar()
# 定义选项的值和文本标签
options = [
("Option 1", 1),
("Option 2", 2),
("Option 3", 3),
("Option 4", 4)
]
# 创建并放置Radiobutton选项
for text, value in options:
radiobutton = Radiobutton(main_window, text=text, variable=selected_option, value=value)
radiobutton.pack(anchor="w")
for text, value in options:
radiobutton = Radiobutton(main_window, text=text, variable=selected_option,
indicatoron = False, value=value)
radiobutton.pack(anchor="w")
Checkbutton: 复选框
复选框部件,允许在选中和取消选中状态。
参数 | 描述 |
master | 父容器 |
text | 显示在复选框旁边的文本标签。 |
variable | 一个Tkinter变量(如IntVar或StringVar),用于存储复选框的状态。 |
onvalue | 当复选框被选中时,关联的Tkinter变量的值。 |
offvalue | 当复选框未被选中时,关联的Tkinter变量的值。 |
command | 当复选框状态变化时调用的函数或方法。 |
image | 复选框旁边显示的图像,可以是Tkinter中的PhotoImage对象。 |
compound | 指定图像和文本标签的排列方式,可以是 |
font | 文本标签的字体。 |
bg | 复选框的背景色。 |
fg | 文本标签的前景色(文本颜色)。 |
activebackground | 复选框在鼠标悬停时的背景色。 |
activeforeground | 文本标签在鼠标悬停时的前景色。 |
selectcolor | 复选框被选中时的颜色(默认是系统特定的颜色)。 |
justify | 文本标签的对齐方式,可以是 |
padx, pady | 文本标签的水平和垂直填充量(以像素为单位)。 |
relief | 复选框的边框样式,可以是 |
width, height | 复选框的宽度和高度(以字符数或像素为单位)。 |
state | 复选框的状态,可以是 |
underline | 在文本标签中显示下划线的字符索引。 |
wraplength | 文本标签的自动换行长度(以像素为单位)。 |
# 创建一个Tkinter变量来存储所选选项的值
option_vars = [(IntVar(value=i), f"选项{i}") for i in range(5)]
for value, option in option_vars:
# 创建并放置Checkbutton选项
checkbutton1 = Checkbutton(master=main_window, text=option, variable=value, onvalue=1, offvalue=0)
checkbutton1.pack()
Menu:菜单栏
用于显示命令的菜单栏或上下文菜单。
参数 | 描述 |
master | 父容器 |
tearoff | 是否允许通过拖动的方式将菜单从菜单栏中拖出,默认为True。 |
title | 菜单的标题,仅适用于顶层菜单栏(MenuBar)。 |
type | 菜单的类型 |
activebackground | 菜单项在鼠标悬停时的背景色。 |
activeforeground | 菜单项在鼠标悬停时的前景色。 |
bg, background | 菜单的背景色。 |
fg, foreground | 菜单的前景色(文本颜色)。 |
font | 菜单项的字体。 |
relief | 菜单的边框样式 |
cursor | 当鼠标在菜单上方时的光标样式。 |
postcommand | 每次弹出菜单时调用的函数或方法。 |
tearoffcommand | 当拖动菜单时调用的函数或方法。 |
takefocus | 是否菜单接受焦点,默认为True。 |
tearoff | 是否显示拖动出来的独立菜单,默认为True。 |
def dummy_command():
print("This is a dummy command.")
# 创建菜单栏
menubar = Menu(master=main_window)
# 创建文件菜单
file_menu = Menu(menubar, tearoff=False)
file_menu.add_command(label="New", command=dummy_command)
file_menu.add_command(label="Open", command=dummy_command)
file_menu.add_command(label="Save", command=dummy_command)
file_menu.add_separator()
file_menu.add_command(label="Exit", command=main_window.quit)
# 创建编辑菜单
edit_menu = Menu(menubar, tearoff=False)
edit_menu.add_command(label="Cut", command=dummy_command)
edit_menu.add_command(label="Copy", command=dummy_command)
edit_menu.add_command(label="Paste", command=dummy_command)
# 将文件和编辑菜单添加到菜单栏
menubar.add_cascade(label="File", menu=file_menu)
menubar.add_cascade(label="Edit", menu=edit_menu)
# 将菜单栏配置到主窗口
main_window.config(menu=menubar)
Menubutton:菜单按钮
点击后打开菜单的按钮部件。
参数 | 描述 |
| Menubutton上显示的文本。 |
| 按钮的外观样式 |
| 文本或图像在Menubutton内部的对齐方式 |
| 当鼠标悬停在Menubutton上时显示的光标类型。 |
| 背景颜色。 |
| 前景(文本)颜色。 |
| Menubutton中文本的字体。 |
| Menubutton的宽度(以字符数或像素数表示)。 |
| Menubutton的高度(以字符数或像素数表示)。 |
| Menubutton的状态 |
| 当Menubutton被点击时调用的函数或方法。 |
| 与Menubutton关联的菜单对象。 |
def dummy_command():
print("This is a dummy command.")
# 创建一个Menubutton
mb = Menubutton(master=main_window, text="Options")
mb.pack(padx=20, pady=20)
# 创建一个菜单,关联到Menubutton
menu = Menu(mb, tearoff=False)
menu.add_command(label="Option 1", command=dummy_command)
menu.add_command(label="Option 2", command=dummy_command)
menu.add_separator()
menu.add_command(label="Exit", command=main_window.quit)
# 将菜单配置到Menubutton
mb.config(menu=menu)
Message:多行文本
显示多行相同字体文本消息的部件,与Label类似。
参数 | 描述 |
| 显示在Message小部件中的文本内容。 |
| 背景颜色。 |
| 前景(文本)颜色。 |
| 文本的字体。 |
| 小部件的宽度(以字符数或像素数表示)。 |
| 文本的对齐方式 |
| 文本或图像在小部件内部的对齐方式 |
| Message小部件周围的水平和垂直填充量。 |
| 小部件的外观样式 |
| 小部件的状态 |
# 创建一个Message小部件
msg = Message(master=main_window,
text="This is a Message widget example",
width=200)
# 设置Message的文本对齐方式
msg.config(justify=CENTER)
# 将Message小部件放置到窗口中
msg.pack(padx=20, pady=20)
Scale:滑动条
用于从范围内选择数值的部件。
参数 | 描述 |
| 滑动条的取值范围。 |
| 滑动条的方向。 |
| 滑动条的长度(水平方向的宽度或垂直方向的高度,以像素为单位)。 |
| 与滑动条关联的变量 |
| 滑动条值变化时调用的回调函数。 |
| 是否显示当前滑动条的值(默认为True)。 |
| 在滑动条上显示刻度的间隔值。 |
| 滑动条的分辨率,即步进值。 |
| 滑动块的长度。 |
| 滑动条的标签。 |
| 标签的锚点 |
| 滑动条的方向 |
| 当滑动条处于活动状态时的背景颜色。 |
| 滑动条的背景和前景(文本)颜色。 |
| 边框的宽度。 |
| 边框的样式 |
scale = Scale(master=main_window, from_=0, to=100, label="滑动条示例", orient="horizontal", tickinterval=10)
scale.pack(fill="x")
scale = Scale(master=main_window, from_=0, to=100, label="滑动条示例", orient="vertical", tickinterval=100)
scale.pack(fill="y", pady=10)
Scrollbar:滚动条
用于在像 Listbox 或 Canvas 等部件中滚动内容的部件,就是下图右侧的滚动条。
参数 | 描述 |
| 滚动条的方向 |
| 滚动条值变化时调用的回调函数,通常与可滚动窗口(如Canvas或Listbox)一起使用。 |
| 滚动条的背景和前景(文本)颜色。 |
| 边框的宽度。 |
| 边框的样式 |
| 滚动条元素的边框宽度。 |
| 滚动条的槽(trough)的颜色。 |
| 滚动条的宽度和高度(以像素为单位)。 |
| 当滚动条处于活动状态时的背景颜色。 |
| 当鼠标悬停在滚动条上时显示的光标样式。 |
| 在用户按住滚动箭头时,滚动条开始连续滚动之前的延迟时间(毫秒)。 |
| 用户按住滚动箭头后,滚动条连续滚动的时间间隔(毫秒)。 |
# 创建一个 Text 组件,允许垂直滚动
text_area = Text(main_window, wrap="word", height=20, width=60)
text_area.pack(padx=10, pady=10, fill="both", side="left")
# 创建一个垂直滚动条,并关联到 Text 组件
scrollbar = Scrollbar(master=main_window, orient="vertical", command=text_area.yview)
scrollbar.pack(side="right", fill="y")
# 将滚动条与 Text 组件关联起来
text_area.config(yscrollcommand=scrollbar.set)
# 插入一些示例文本到 Text 组件中
example_text = "这是一个示例文本框,用于演示滚动条的使用。\n" * 80
text_area.insert(END, example_text)
Toplevel:弹窗
浮在所有其他窗口上方的窗口部件,可以用来创建参数配置窗口或者信息提示窗口,类似主窗口 Tk()。
参数 | 描述 |
| 指定窗口的类名,可以影响窗口的外观和行为。 |
| 窗口的背景颜色。 |
| 窗口的边框宽度。 |
| 当鼠标悬停在窗口上时显示的光标样式。 |
| 窗口的高度(以像素为单位)。 |
| 窗口的宽度(以像素为单位)。 |
| 窗口边框的颜色(无焦点时)。 |
| 窗口边框的颜色(有焦点时)。 |
| 窗口边框的宽度。 |
| 边框的样式 |
| 是否接受键盘焦点,默认为 True。 |
| 窗口的标题栏文本。 |
| 与窗口关联的菜单栏。 |
| 设置为另一个窗口,使该窗口成为其模态(modal)对话框。 |
| 关闭窗口时调用的函数。 |
| 窗口关闭时执行的回调函数。 |
| 窗口的状态 |
| 窗口左上角图标的位图。 |
| 最小化窗口。 |
| 窗口的几何大小和位置,例如:"400x300+100+100" 表示宽400像素,高300像素,位于屏幕左上角(100, 100)的位置。 |
def open_new_window():
new_window = Toplevel()
new_window.title("新窗口")
new_window.geometry("300x200+200+200")
new_window.config(bg="light blue", bd=10, relief=RIDGE)
label = Label(new_window, text="这是一个新窗口!")
label.pack(padx=20, pady=20)
button_close = Button(new_window, text="关闭", command=new_window.destroy)
button_close.pack()
button_open = Button(master=main_window, text="打开新窗口", command=open_new_window)
button_open.pack(pady=50)
Spinbox:数值选择
使用箭头从固定选项集中选择值的部件。
参数 | 描述 |
| 背景颜色。 |
| 边框宽度。 |
| 当鼠标悬停在Spinbox上时显示的光标样式。 |
| 文本字体。 |
| 前景(文本)颜色。 |
| 允许的最小值。 |
| 允许的最大值。 |
| 每次点击箭头按钮或按上下键时增加或减少的值。 |
| 与Spinbox关联的Tkinter变量,用于获取或设置Spinbox的值。 |
| Spinbox的状态 |
| Spinbox的宽度(以字符数为单位)。 |
| 文本对齐方式 |
| 值变化时调用的回调函数。 |
def show_value():
value = spinbox_var.get()
print(f"当前选择的值是:{value}")
spinbox_var = StringVar()
spinbox = Spinbox(master=main_window, from_=0, to=10, width=5, textvariable=spinbox_var,
command=show_value)
spinbox.pack(pady=20)
spinbox_var2 = StringVar()
spinbox = Spinbox(master=main_window, from_=0, to=100, width=100, textvariable=spinbox_var2,
command=show_value)
spinbox.pack(pady=20)
PanedWindow:窗格容器
带有可以由用户调整大小的窗格的容器部件,可以用来调整工具栏和主视图。
参数 | 描述 |
| 背景颜色。 |
| 边框宽度。 |
| 当鼠标悬停在PanedWindow上时显示的光标样式。 |
| 分格窗口的方向 |
| 分隔条(分割窗格的条状区域)的宽度。 |
| 分隔条的边框样式 |
| 拖动分隔条时手柄的大小。 |
| 分隔条的大小。 |
| PanedWindow的高度(仅当 |
| PanedWindow的宽度(仅当 |
# 创建一个水平方向的PanedWindow
paned_window = PanedWindow(master=main_window, orient=HORIZONTAL, sashwidth=5, sashrelief=RAISED)
paned_window.pack(fill=BOTH, expand=True)
# 添加两个子窗格
left_frame = Frame(paned_window, bg="light blue", width=100, height=200)
paned_window.add(left_frame)
right_frame = Frame(paned_window, bg="light green", width=200, height=200)
paned_window.add(right_frame)
Canvas : 画布
用于绘制图形、线条、形状和图像的区域, 可以与 turtle 绘画库搭配使用。
参数 | 描述 |
| 画布的背景颜色。 |
| 画布的边框宽度。 |
| 当鼠标悬停在画布上时显示的光标样式。 |
| 画布的高度。 |
| 画布的宽度。 |
# 创建一个画布
canvas = Canvas(master=main_window, bg="white", width=400, height=300, bd=2, relief=SUNKEN)
canvas.pack()
# 绘制一个矩形
rect = canvas.create_rectangle(50, 50, 150, 100, fill="blue")
# 绘制一个椭圆
oval = canvas.create_oval(200, 50, 300, 100, fill="red")
ttk :Themed widgets
现代外观风格的部件,说白了就是和原始的部件功能差不多,只是外观,性能,兼容性都有很大的提升。学完原始的部件可以直接使用 ttk, 我强烈建议使用 ttk.
- 现代外观和风格:
ttk
部件提供了现代化的外观和风格,相比于标准的Tkinter部件,它们看起来更加平滑、一致,并且更符合当前用户界面设计的标准。这使得你的应用程序在视觉上更具吸引力,用户体验也更好。 - 主题支持:
ttk
允许你选择不同的主题样式,以适应不同操作系统或用户界面风格的需求。这意味着你可以在不同的平台上保持一致的外观,而不必担心部件在不同系统上的差异。 - 更多的功能和控制: 一些
ttk
部件比其标准Tkinter对应部件提供了更多的功能和控制选项。例如,ttk.Combobox
可以提供更好的下拉选择功能,ttk.Treeview
可以支持更复杂的数据展示和编辑等。 - 性能优化: 尽管不是所有情况下都显著,但
ttk
部件通常能够比标准Tkinter部件更高效地绘制和渲染,这对于复杂的界面或者需要频繁刷新的情况下尤为重要。
以下部件是 ttk 新增的部件:
tk.OptionMenu:菜单选项
参数名 | 描述 |
| 父容器 |
| 一个 tkinter 变量对象,用于存储用户选择的值。通常是 |
| 当用户选择一个新值时,调用的回调函数。 |
| 与 |
# 创建一个 StringVar 变量对象
selected_option = StringVar()
# 设置初始值
optionList = ('train', 'plane', 'boat','2345','234567')
selected_option.set(optionList[0])
# 创建 OptionMenu
option_menu = ttk.OptionMenu(main_window, selected_option, *optionList)
option_menu.pack(padx=20, pady=20)
ttk.Combobox: 下拉选择框
下拉组合框,功能类似于 tk.OptionMenu,但提供了更好的用户交互体验。
参数 | 描述 |
| 设置Combobox的选项值列表,可以是一个字符串列表或元组。 |
| 与Combobox关联的Tkinter变量,用于获取或设置用户选择的值。 |
| 设置Combobox的状态,可以是 |
| 设置Combobox的宽度(以字符数为单位)。 |
| 设置Combobox的高度(以显示的行数为单位)。 |
| 设置Combobox的字体。 |
| 设置Combobox的前景色(文本颜色)。 |
| 设置Combobox的背景色。 |
| 设置Combobox中文本的对齐方式,可以是 |
| 指定一个回调函数,在Combobox下拉列表被弹出前调用。 |
| 设置验证的模式,可以是 |
| 设置验证函数,用于验证用户输入。 |
| 设置一个回调函数,当验证失败时调用。 |
| 设置一个回调函数,在Combobox水平滚动时调用。 |
| 设置是否循环滚动,默认为 |
def on_select(event):
selected_value.set(combobox.get())
print(f"Selected: {selected_value.get()}")
# 创建一个变量来存储选定的值
selected_value = StringVar()
# 创建一个Combobox部件
combobox = ttk.Combobox(master=main_window, textvariable=selected_value, width=20, state='readonly')
combobox['values'] = ('Option 1', 'Option 2', 'Option 3', 'Option 4')
combobox.pack(side="left",expand=True)
combobox.current(0) # 设置默认选中第一个选项
# 添加一个事件绑定,当选项改变时触发
combobox.bind("<<ComboboxSelected>>", on_select)
# 显示选中的值的标签
selected_label = ttk.Label(master=main_window, textvariable=selected_value)
selected_label.pack(side="right")
ttk.Treeview: 树形视图
树形视图控件,用于展示和编辑层级数据。
参数 | 描述 |
| 列表,用于指定表格中的列,可以包含多个列名。 |
| 列表,指定在 Treeview 中显示的列,可以是 |
| 选择模式,可以是 |
| 指定显示哪些部件,如 |
| 设置显示的行数。 |
| 内边距,指定项内文本与边框之间的空间。 |
| 应用的样式。 |
| 设置一个回调函数,在垂直滚动时调用。 |
| 设置一个回调函数,在水平滚动时调用。 |
| 选中项的背景色。 |
| 选中项的前景色。 |
| 添加子项的位置,默认是最后。 |
| 在父项中插入子项。 |
| 在树形结构中添加子项。 |
| 编辑树形结构中的项目。 |
# 创建Treeview部件
tree = ttk.Treeview(master=main_window, columns=('Type', 'Size'), selectmode='browse')
# 设置列名和列宽
tree.heading('#0', text='Name')
tree.heading('Type', text='Type')
tree.heading('Size', text='Size')
tree.column('#0', width=150)
tree.column('Type', width=100)
tree.column('Size', width=100)
# 插入数据
# 插入根节点
folder1 = tree.insert('', 'end', 'folder1', text='Folder 1', values=('Folder', ''))
folder2 = tree.insert('', 'end', 'folder2', text='Folder 2', values=('Folder', ''))
# 插入子节点
file1 = tree.insert(folder1, 'end', 'file1', text='File 1', values=('File', '10 KB'))
file2 = tree.insert(folder1, 'end', 'file2', text='File 2', values=('File', '20 KB'))
subfolder = tree.insert(folder1, 'end', 'subfolder', text='Subfolder', values=('Folder', ''))
# 插入子节点
file3 = tree.insert(subfolder, 'end', 'file3', text='File 3', values=('File', '15 KB'))
# 插入子节点
file4 = tree.insert(folder2, 'end', 'file4', text='File 4', values=('File', '5 KB'))
# 选中第一个根节点
tree.selection_set('folder1')
# 显示Treeview
tree.pack(expand=True, fill=BOTH)
ttk.Progressbar: 进度条
用于显示任务完成的进度。
参数 | 描述 |
| 进度条的方向,可以是 |
| 进度条的长度,单位是像素。 |
| 进度条的模式,可以是 |
| 进度条的最大值,通常默认为 100。 |
| 当前进度条的值,用来表示当前的完成进度。 |
| 与进度条相关联的变量,可以通过设置该变量来动态更新进度条的值。 |
| 进度条的样式名称,可以通过设置不同的样式来改变进度条的外观。 |
| 进度条的最大值,用于确定进度条的百分比完成度。 |
| 进度条的长度,通常以像素为单位。 |
| 进度条的模式,可以是 "determinate"(确定模式,显示当前值)或 "indeterminate"(不确定模式,用于表示任务正在进行但进度不明)。 |
def simulate_progress():
progress_bar['value'] += 10
if progress_bar['value'] < 100:
main_window.after(500, simulate_progress)
# 创建Progressbar部件
progress_bar = ttk.Progressbar(master=main_window, orient='horizontal', length=300, mode='determinate')
# 设置进度条的样式和长度
progress_bar.pack(pady=20)
# 模拟进度
start_button = ttk.Button(master=main_window, text="Start Progress", command=simulate_progress)
start_button.pack()
ttk.Notebook: 多页面容器
用于显示多个标签页,每个标签页可以包含不同的内容。
参数 | 描述 |
| Notebook 部件的高度,通常以像素为单位。 |
| Notebook 部件的宽度,通常以像素为单位。 |
| Notebook 内部选项卡与边框的内边距大小。 |
| 用于设置选项卡的位置,可以是 |
| 用于自定义 Notebook 外观的样式名称。 |
| 如果设置为 True,则 Notebook 可以接收焦点。默认为 True。 |
| Notebook 部件的 CSS 类名称,用于进一步自定义样式。 |
| 当鼠标悬停在 Notebook 上时的光标样式。 |
| 部件的状态,可以是 |
| 选中选项卡时的背景颜色。 |
| Notebook 的背景色。 |
| 文本的前景色。 |
# 创建 Notebook 部件
notebook = ttk.Notebook(master=main_window)
# 创建第一个选项卡
tab1 = ttk.Frame(notebook)
notebook.add(tab1, text='Tab 1')
# 在第一个选项卡中添加一些内容
label1 = ttk.Label(tab1, text="This is Tab 1")
label1.pack(padx=20, pady=20)
# 创建第二个选项卡
tab2 = ttk.Frame(notebook)
notebook.add(tab2, text='Tab 2')
# 在第二个选项卡中添加一些内容
label2 = ttk.Label(tab2, text="This is Tab 2")
label2.pack(padx=20, pady=20)
# 将 Notebook 放置到主窗口中
notebook.pack(expand=True, fill=BOTH)
ttk.Separator:分隔符
用于创建分隔符(Separator)的部件,通常用于在 GUI 中分隔不同部分或者组件。
参数名 | 描述 |
| 分隔符的方向,可以是 |
| 应用于分隔符的样式名称。样式必须在创建 |
| 分隔符的厚度,即宽度或高度(取决于方向)。默认是 1 像素。 |
# 创建一个水平分隔符
horizontal_sep = ttk.Separator(master=main_window, orient='horizontal')
horizontal_sep.pack(fill='x', padx=5, pady=10, side="top")
# 创建一个垂直分隔符
vertical_sep = ttk.Separator(master=main_window, orient='vertical')
vertical_sep.pack(fill='y', padx=10, pady=5, side="right")
main_window.mainloop()
结语:
现在我们对 Tk 已经有了初步了解,接下来就得动手实践了。你可以发挥你的创意设计一款小工具,比如计算器,选色器,音乐播放器等。在每个小项目的开始,你应该做的并不是直接写代码,而是使用绘图工具或者手绘的方式将设计图画出来,设计的时候要联系到 Tk 里的相应部件。至少经过两次的设计,你再开始编写代码,代码应分解功能模块,然后进行组装。不会的技术点可以谷歌或者百度,我相信在实践的过程中你将学到更多知识,且不仅限于技术。
当然,如果你是小白,没有项目经验,你可以花费几瓶可乐钱购买我的项目源码,每个项目都包含详细的开发文档,帮助你从思想层面出发,教你如何思考并构建一个目标程序。
媒体播放器:
手把手教你写一个媒体播放器:
https://www.yuque.com/xcbyyy/yo0qnh/tbg36feucy8x1tc1
附录:
变量
在 tkinter 模块中,有几种特定的变量类别用于与 GUI 组件之间进行数据绑定和交互。
- Variable:
-
- 这是 tkinter 中所有变量类的基类。通常不直接使用,而是通过其派生类(如
StringVar
,IntVar
,DoubleVar
,BooleanVar
)来创建具体类型的变量对象。 - 方法:
set(value)
,get()
等。可以用来设置和获取变量的值。
- 这是 tkinter 中所有变量类的基类。通常不直接使用,而是通过其派生类(如
- StringVar:
-
StringVar
是用于绑定和操作字符串类型数据的 tkinter 变量类。- 方法:
set(value)
: 设置变量的值为字符串value
;get()
: 获取当前变量的字符串值。 - 应用:常用于与
Entry
,Label
,Button
等部件绑定,实现动态更新和显示文本内容。
- IntVar:
-
IntVar
用于绑定和操作整数类型数据的 tkinter 变量类。- 方法:
set(value)
: 设置变量的值为整数value
;get()
: 获取当前变量的整数值。 - 应用:通常用于与
Checkbutton
,Radiobutton
,Scale
等部件绑定,控制整数值的选项或者状态。
- DoubleVar:
-
DoubleVar
用于绑定和操作浮点数类型数据的 tkinter 变量类。- 方法:
set(value)
: 设置变量的值为浮点数value
;get()
: 获取当前变量的浮点数值。 - 应用:类似于
IntVar
,但适用于需要处理浮点数的部件和情况。
- BooleanVar:
-
BooleanVar
用于绑定和操作布尔类型数据的 tkinter 变量类。- 方法:
set(value)
: 设置变量的值为布尔值value
;get()
: 获取当前变量的布尔值。 - 应用:主要用于与
Checkbutton
部件绑定,实现选中状态的控制和反映。
颜色:
默认字符串选项: 'white', 'black', 'red', 'green', 'blue', 'cyan', 'yellow', 'magenta'
#rgb | 3个16位 |
#rrggbb | 6个16位 |
#rrrgggbbb | 9个16位 |
锚点 anchors:
边框样式 relief:
flat,raised,sunken,groove,ridge
小图标 bitmap :
'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question', 'warning'
游标样式 cursor :
Style样式: