Tkinter 是使用 python 进行窗口视窗设计的模块。Tkinter模块(“Tk 接口”)是Python的标准Tk GUI工具包的接口。作为 python 特定的GUI界面,是一个图像的窗口,tkinter是python自带的,可以编辑的GUI界面,用来入门,熟悉窗口视窗的使用,非常有必要。
提供tk支持的模块包括:
模块 | 说明 |
---|---|
tkinter | TK主模块 |
tkinter.colorchooser | 让用户选择颜色的对话框。 |
tkinter.commondialog | 其他模块定义的对话框的基类。 |
tkinter.filedialog | 允许用户指定文件的通用对话框,用于打开或保存文件。 |
tkinter.font | 帮助操作字体的工具。 |
tkinter.messagebox | 访问标准的 Tk 对话框。 |
tkinter.scrolledtext | 内置纵向滚动条的文本组件。 |
tkinter.simpledialog | 基础对话框和一些便捷功能。 |
tkinter.ttk | Tk 8.5中引入的主题小部件集,为tkinter主模块中的许多经典小部件提供了现代替代品。 |
首先,我们导入tkinter的库。
# 导入tkinter库 from tkinter import * # 创建一个窗口 window = Tk() # 设置窗口标题 window.title("窗口标题栏") # 设置窗口显示尺寸 window.geometry("500x400") # 进入消息循环,显示窗口 window.mainloop()
结果如图所示:
窗口居中显示:
# 获取屏幕的宽度和高度
screenwidth = window.winfo_screenwidth()
screenheight = window.winfo_screenheight()
# 计算窗口左上角的坐标,使窗口居中显示
x = int(screenwidth / 2 - 500 / 2) # 窗口左上角的 x 坐标
y = int(screenheight / 2 - 400 / 2) # 窗口左上角的 y 坐标
# 设置窗口大小和位置
size = '{}x{}+{}+{}'.format(500, 400, x, y) # 窗口的大小和位置
window.geometry(size) # 设置窗口的几何属性,即大小和位置
Tkinter的提供各种控件,如按钮,标签和文本框等,这些控件通常被称为控件或者部件。目前 Tkinter中常用的 15 个控件,如下所示:
控件类型 | 控件名称 | 控件作用 |
---|---|---|
Button | 按钮 | 点击按钮时触发/执行一些事件(函数) |
Canvas | 画布 | 提供绘制图,比如直线、矩形、多边形等 |
Checkbutton | 复选框 | 多项选择按钮,用于在程序中提供多项选择框 |
Entry | 文本框输入框 | 用于接收单行文本输入 |
Frame | 框架(容器)控件 | 定义一个窗体(根窗口也是一个窗体),用于承载其他控件,即作为其他控件的容器 |
Label | 标签控件 | 用于显示单行文本或者图片 |
LabelFrame | 容器控件 | 一个简单的容器控件,常用于复杂的窗口布局。 |
Listbox | 列表框控件 | 以列表的形式显示文本 |
Menu | 菜单控件 | 菜单组件(下拉菜单和弹出菜单) |
Menubutton | 菜单按钮控件 | 用于显示菜单项 |
Message | 信息控件 | 用于显示多行不可编辑的文本,与 Label控件类似,增加了自动分行的功能 |
messageBox | 消息框控件 | 定义与用户交互的消息对话框 |
OptionMenu | 选项菜单 | 下拉菜单 |
PanedWindow | 窗口布局管理组件 | 为组件提供一个框架,允许用户自己划分窗口空间 |
Radiobutton | 单选框 | 单项选择按钮,只允许从多个选项中选择一项 |
Scale | 进度条控件 | 定义一个线性“滑块”用来控制范围,可以设定起始值和结束值,并显示当前位置的精确值 |
Spinbox | 高级输入框 | Entry 控件的升级版,可以通过该组件的上、下箭头选择不同的值 |
Scrollbar | 滚动条 | 默认垂直方向,鼠标拖动改变数值,可以和 Text、Listbox、Canvas等控件配合使用 |
Text | 多行文本框 | 接收或输出多行文本内容 |
Toplevel | 子窗口 | 在创建一个独立于主窗口之外的子窗口,位于主窗口的上一层,可作为其他控件的容器 |
后续我们将进行部分组件的案例演示。
Python Tkinter 标签控件(Label)指定的窗口中显示的文本和图像。
属性名称 | 说明 |
---|---|
anchor | 控制文本(或图像)在 Label 中显示的位置(方位),通过方位的英文字符串缩写(n、ne、e、se、s、sw、w、nw、center)实现定位,默认为居中(center) |
bg | 用来设置背景色 |
bd | 即 borderwidth 用来指定 Label 控件的边框宽度,单位为像素,默认为 2 个像素 |
bitmap | 指定显示在 Label 控件上的位图,若指定了 image 参数,则该参数会被忽略 |
compound | 控制 Lable 中文本和图像的混合模式,若选项设置为 CENTER,则文本显示在图像上,如果将选项设置为 BOTTOM、LEFT、RIGHT、TOP,则图像显示在文本旁边。 |
cursor | 指定当鼠标在 Label 上掠过的时候,鼠标的的显示样式,参数值为 arrow、circle、cross、plus |
disableforeground | 指定当 Label 设置为不可用状态的时候前景色的颜色 |
font | 指定 Lable 中文本的 (字体,大小,样式)元组参数格式,一个 Lable 只能设置一种字体 |
fg | 设置 Label 的前景色 |
height/width | 设置 Lable 的高度/宽度,如果 Lable 显示的是文本,那么单位是文本单元,如果 Label 显示的是图像,那么单位就是像素,如果不设置,Label 会自动根据内容来计算出标签的高度 |
highlightbackground | 当 Label 没有获得焦点的时候高亮边框的颜色,系统的默认是标准背景色 |
highlightcolor | 指定当 Lable 获得焦点的话时候高亮边框的颜色,系统默认为0,不带高亮边框 |
image | 指定 Label 显示的图片,一般是 PhotoImage、BitmapImage 的对象 |
justify | 表示多行文本的对齐方式,参数值为 left、right、center,注意文本的位置取决于 anchor 选项 |
padx/pady | padx 指定 Label 水平方向上的间距(即内容和边框间),pady 指定 Lable 水平方向上的间距(内容和边框间的距离) |
relief | 指定边框样式,默认值是 "flat",其他参数值有 "groove"、"raised"、"ridge"、"solid"或者"sunken" |
state | 该参数用来指定 Lable 的状态,默认值为"normal"(正常状态),其他可选参数值有"active"和"disabled" |
takefocus | 默认值为False,如果是 True,表示该标签接受输入焦点 |
text | 用来指定 Lable 显示的文本,注意文本内可以包含换行符 |
underline | 给指定的字符添加下划线,默认值为 -1 表示不添加,当设置为 1 时,表示给第二个文本字符添加下划线。 |
wraplength | 将 Label 显示的文本分行,该参数指定了分行后每一行的长度,默认值为 0 |
基本案例:
# 创建一个标签 lb = Label(window, text="书本名称:", font=("宋体", 12)) # 设置标签在窗口的显示位置 lb.place(x=10, y=10)
Entry 控件是 Tkinter GUI 编程中的基础控件之一,它的作用就是允许用户输入内容,从而实现 GUI 程序与用户的交互,比如当用户登录软件时,输入用户名和密码,此时就需要使用 Entry 控件。
基本属性:
属性名称 | 说明 |
---|---|
exportselection | 默认情况下,如果在输入框中选中文本会复制到粘贴板,如果要忽略这个功能,可以设置为 exportselection=0 |
selectbackground | 选中文字时的背景颜色 |
selectforeground | 选中文字时的前景色 |
show | 指定文本框内容以何种样式的字符显示,比如密码可以将值设为 show="*" |
textvariable | 输入框内值,也称动态字符串,使用 StringVar() 对象来设置,而 text 为静态字符串对象 |
xscrollcommand | 设置输入框内容滚动条,当输入的内容大于输入框的宽度时使用户 |
常用方法:
方法 | 说明 |
---|---|
delete() | 根据索引值删除输入框内的值 |
get() | 获取输入框内的值 |
set() | 设置输入框内的值 |
insert() | 在指定的位置插入字符串 |
index() | 返回指定的索引值 |
select_clear() | 取消选中状态 |
select_adujst() | 确保输入框中选中的范围包含 index 参数所指定的字符,选中指定索引和光标所在位置之前的字符 |
select_from (index) | 设置一个新的选中范围,通过索引值 index 来设置 |
select_present() | 返回输入框是否有处于选中状态的文本,如果有则返回 true,否则返回 false。 |
select_to() | 选中指定索引与光标之间的所有值 |
select_range() | 选中指定索引与光标之间的所有值,参数值为 start,end,要求 start 必须小于 end。 |
基本案例:
# 创建一个文本框 tx = Entry(window, width=20) tx.place(x=100, y=10)
Button 控件是 Tkinter 中常用的窗口部件之一,同时也是实现程序与用户交互的主要控件。通过用户点击按钮的行为来执行回调函数,是 Button 控件的主要功用。首先自定义一个函数或者方法,然后将函数与按钮关联起来,最后,当用户按下这个按钮时,Tkinter 就会自动调用相关函数。
基本属性:
属性 | 说明 |
---|---|
anchor | 控制文本所在的位置,默认为中心位置(CENTER) |
activebackground | 当鼠标放在按钮上时候,按妞的背景颜色 |
activeforeground | 当鼠标放在按钮上时候,按钮的前景色 |
bd | 按钮边框的大小,默认为 2 个像素 |
bg | 按钮的背景色 |
command | 用来执行按钮关联的回调函数。当按钮被点击时,执行该函数 |
fg | 按钮的前景色 |
font | 按钮文本的字体样样式 |
height | 按钮的高度 |
highlightcolor | 按钮控件高亮处要显示的颜色 |
image | 按钮上要显示的图片 |
justify | 按钮显示多行文本时,用来指定文本的对齐方式,参数值有 LEFT/RIGHT/CENTER |
padx/pady | padx 指定 x 轴(水平方向)的间距大小,pady 则表示 y轴(垂直方向)的间距大小 |
ipadx/ipady | ipadx 指标签文字与标签容器之间的横向距离;ipady 则表示标签文字与标签容器之间的纵向距离 |
state | 设置按钮的可用状态,可选参数有NORMAL/ACTIVE/DISABLED,默认为 NORMAL |
text | 按钮控件要显示的文本 |
基本案例:
# 导入tkinter模块 from tkinter import * # 导入tkinter模型中的messagebox from tkinter import messagebox # 给按钮绑定点击事件 def do_click(): # 触发按钮点击事件之后,获取文本框输入的值 text = tx.get() print(f"被点击了,text={text}") messagebox.showinfo("提示", text) # 创建一个按钮 btn_search = Button(window, text="点我试试", width=6, command=do_click) btn_search.place(x=260, y=5)
更多组件的基本使用请见此处资料。
ttk.Treeview 控件可将多项内容分层级显示。每个数据项抖带有一个文本标签、一张图片(可选)和一个数据列表(可选)。这些数据值将在树标签后面分列显示。
基本属性:
属性 | 描述 |
---|---|
columns | 列标识的列表,定义了列的数量和名称。 |
displaycolumns | 列标识的列表(索引可为符号或整数),指定要显示的数据列及显示顺序,或为字符串 “#all”。 |
height | 指定可见的行数。注意:所需宽度由各列宽度之和决定。 |
padding | 指定控件内部的留白。为不超过四个元素的长度列表。 |
selectmode | 控制内部类如何进行选中项的管理。可为 extended、browse 或 none。若设为 extended(默认),则可选中多个项。若为 browse ,则每次只能选中一项。若为 none,则无法修改选中项。请注意,代码和 tag 绑定可自由进行选中操作,不受本属性的限制。 |
show | 由0个或下列值组成的列表,指定要显示树的哪些元素。tree :在 #0 列显示树的文本标签。headings :显示标题行。默认为“tree headings”,显示所有元素。 注意 :第 #0 列一定是指 tree 列,即便未设置 show="tree" 也一样。 |
基本案例:
# 导入Treeview组件 from tkinter.ttk import Treeview # 创建TreeView组件 # show="headings" 用于隐藏首列 tv = Treeview(window, columns=("id", "bookname", "price", "booktype"), show="headings") # 设置Treeview显示位置 tv.place(x=10, y=40)
常用方法:
方法 | 描述 |
---|---|
bbox(item, column=None) | 返回指定item的框选范围,或者单元格的框选范围 |
column( cid, option=None, **kw) | 设置或者查询某一列的属性 |
delete(*items) | 删除指定行或者节点(含子节点) |
vdetach(*items) | 与delete类似,不过不是真正删除,而是隐藏了相关内容。可以用move方法重新显示v |
exists(item) | 判断指定的item是否存在 |
focus(item=None) | 获得选定item的iid,或者选中指定item。 |
get_children(item=None) | 返回指定item的子节点 |
heading(column, option=None, **kw) | 设置或者查询表头行的配置参数 |
identify(component, x, y) | 返回在坐标(x,y)处的部件信息。部件包括:region(heading,cell等), item, column, row, 和 element。 |
identify_element(x, y) | 返回在(x,y)处的元素。 |
identify_region(x, y) | 返回坐标(x,y)处的Tree view组成部分 |
identify_row(y) | 给定y坐标,返回指定item索引 |
index(item) | 返回数字化的item索引,从0开始 |
set_children(item, *newchildren) | 设置item的新子节点为newchildren,现有的子节点会被移除。一般用于树形结构中。 |
insert(parent, index, iid=None, **kw) | 插入一个新的item |
item(item, option=None, **kw) | 返回item节点的相关信息 |
move(item, parent, index) | move()方法有两种作用: (1)将detach的item重新显示(reattach) (2)移动item指定的节点到parent的子节点中,位置由index指定 |
next(item) | 返回item的下一个节点 |
parent(item) | 返回item的父节点 |
prev(item) | 返回item的前一个节点 |
see(item) | 保证item指定的节点在Treeview控件中可见 |
selection(items=None) | 返回当前选定的节点的iid |
selection_set(*items) | 选中items指定的节点 |
selection_remove(*items) | 从当前选择中移除items指定的节点 |
selection_add(*items) | 将items指定的节点添加到当前的选择中 |
selection_toggle(*items) | 选中的节点变为不选中,未选中的节点变为选中 |
set(item, column=None, value=None) | 设置或者获得节点信息 |
tag_bind( tagname, sequence=None, callback=None) | 给tagname指定的tag绑定事件以及回调函数 |
tag_configure( tagname, option=None, **kw) | 配置或者获得tag的有关信息 |
tag_has(tagname, item=None) | 判断tag是否存在或者是tag与那些节点关联 |
column列选项
column( cid, option=None, **kw)
查询或者修改指定列的配置。cid可以是整数,也可以列的别名。如果不输入option,则返回目前的配置选项字典。Treeview列的选项有:
选项 | 含义 |
---|---|
anchor | 对齐模式。取值有n,e,s,w,ne,nw,se,sw和center。 |
id | 列的名称或者标识 |
minwidth | 列的最小宽度,调整列宽的时候,不会小于这个数值。默认值是20 |
stretch | 是否随着窗口大小的调整而拉伸Treeview。默认值是True |
width | 定义列宽。默认值是200 |
基础案例:
# 设置列的宽度及对齐方式 # tv.column("#0",width=10) tv.column("id", width=90, anchor=CENTER) tv.column("bookname", width=200, anchor=CENTER) tv.column("price", width=96, anchor=CENTER) tv.column("booktype", width=90, anchor=CENTER)
heading表头行:
heading(column, option=None, **kw)
设置或者查询表头行的配置参数。如果是表格形式的,column是列的位置(就是第几列,从0计数)或者列的别名。如果是树形结构的(比如文件目录),column的值为'#0'。 如果没有option参数,返回的是当前的配置数据。 heading的选项有:
选项 | 含义 |
---|---|
anchor | 对齐模式。取值有n,e,s,w,ne,nw,se,sw和center。 |
command | 与指定列相关的回调函数 |
image | 在表头显示图片 |
text | 在表头显示文本 |
state | 当前列的状态 |
基本案例:
# 设置列的表头 # tv.heading("#0",text="") tv.heading("id", text="书本编号") tv.heading("bookname", text="书本名称") tv.heading("price", text="书本价格") tv.heading("booktype", text="书本类型")
insert新增数据行:
insert(parent, index, iid=None, **kw)
插入一个新的item。 (1)parent 对于表格类型的Treeview,parent一般为空。对于树形类型的Treeview,parent为父节点。 (2)index 指明在何处插入新的item。可以是'end',也可以是数字。比如,如果要让新插入的item成为第一个子节点或者在第一行,index就设为0。如果是第二个子节点或者第二行,就是设置index=1。如果在最末端插入item,就设置index='end' (3)iid 如果没有赋值,就使用系统自动生成的id。如果输入了id,必须保证与现有的id不重复。否则系统会自动生成id。 (4)**kw 设置插入item的属性。支持的属性有:
选项 | 含义 |
---|---|
image | 显示图像 |
open | 针对树形结构,确认插入的item是打开还是折叠状态。True打开,False为折叠。 |
tags | 为新插入的item设置tag标签 |
text | 显示文字 |
values | 在表格结构中,要显示的数值。这些数值是按照逻辑结构赋值的,也就是按照columns设定的列次序来赋值。如果输入的个数少于columns指定列数,则插入空白字符串 |
基本案例:
# 数据绑定 tv.insert('', END, values=(1, "山海经", 100, '玄幻')) tv.insert('', END, values=(2, "金刚经", 110, '经书')) tv.insert('', END, values=(3, "三字经", 120, '内功心法')) tv.insert('', END, values=(4, "道德经", 100, '内功心法'))
另一种
import tkinter as tk # 导入 tkinter 库,用于创建 GUI 程序
import tkinter.ttk as ttk # 导入 tkinter.ttk 模块,用于创建包含主题小部件的 GUI 程序
# 创建根窗口
root = tk.Tk()
root.title("简单示例")
# 设置窗口大小
root.geometry('400x400')
# 创建一个Treeview
tree = ttk.Treeview(root, show='tree')
tree.pack()
# 添加一级树节点
treeF1 = tree.insert("", 0, '北京', text='中国北京', values=('F1'))
treeF2 = tree.insert("", 1, '河北', text='中国河北', values=('F2'))
treeF3 = tree.insert("", 2, '广州', text='中国广州', values=('F3'))
# 添加二级树节点
treeF1_1 = tree.insert(treeF1, 0, '东城区', text='北京东城区', values=('F1_1'))
treeF1_2 = tree.insert(treeF1, 1, '西城区', text='北京西城区', values=('F1_2'))
treeF2_1 = tree.insert(treeF2, 0, '石家庄', text='河北石家庄', values=('F2_1'))
treeF2_2 = tree.insert(treeF2, 1, '邯郸', text='河北邯郸', values=('F2_2'))
# 添加三级树节点
treeF2_2_1 = tree.insert(treeF2_2, 0, '永年区', text='河北石家庄永年区', values=('F2_2_1'))
treeF2_2_2 = tree.insert(treeF2_2, 1, '丹山区', text='河北邯郸丹山区', values=('F2_2_2'))
# 开始运行主事件循环
tk.mainloop()
DBHelper只是对基本操作进行了简单封装处理:
from pymysql import * # 导入 pymysql 库中的所有内容,包括 Connection、Cursor 等
from pymysql.cursors import Cursor # 从 pymysql.cursors 模块中导入 Cursor 类
class DBHelper:
conn: Connection = None # 初始化 Connection 对象为 None,用于存储数据库连接
curs: Cursor = None # 初始化 Cursor 对象为 None,用于执行 SQL 查询和操作数据库
def __init__(self):
# 在初始化方法中建立数据库连接
self.conn = Connection(user="root", password="1234",
port=3306, host="localhost",
database="vue", charset="utf8",
autocommit=True)
self.curs = self.conn.cursor() # 初始化 Cursor 对象
def close(self):
self.curs.close() # 关闭 Cursor 对象
self.conn.close() # 关闭数据库连接
def execute(self, sql: str, params: tuple):
try:
self.curs.execute(sql, params) # 执行 SQL 操作
except Exception as ex:
print(f"操作失败,提示:{ex}") # 操作失败时打印异常信息
finally:
self.close() # 最终关闭数据库连接
def find(self, sql: str, params: tuple):
try:
self.curs.execute(sql, params) # 执行 SQL 查询
return self.curs.fetchall() # 返回查询结果
except Exception as ex:
print(f"查询失败,提示:{ex}") # 查询失败时打印异常信息
finally:
self.close() # 最终关闭数据库连接
return None # 如果查询失败,返回 None
from utils.DBHelper import * # 导入 DBHelper 类,用于操作数据库
class BookDao:
db = None # 初始化 DBHelper 对象为 None
def __init__(self):
self.db = DBHelper() # 初始化 DBHelper 对象,用于数据库操作
def add(self, book: tuple = None):
sql = """insert into t_book_vue(bookname,price,booktype) values(%s,%s,%s)""" # 插入图书信息的 SQL 语句
self.db.execute(sql, book) # 执行插入操作
def query(self, book: tuple = None):
sql = "select * from t_book_vue where bookname like %s" # 查询图书信息的 SQL 语句
return self.db.find(sql, book) # 执行查询操作并返回结果
def delete(self, bid: int = 0):
sql = """delete from t_book_vue where id=%s""" # 删除图书信息的 SQL 语句
self.db.execute(sql, (bid,)) # 执行删除操作
if __name__ == '__main__':
bd = BookDao() # 创建 BookDao 实例
# bd.add(("222",123,"22")) # 调用 add 方法插入图书信息
# print(bd.query(('%%',))) # 调用 query 方法查询图书信息
# bd.delete(56) # 调用 delete 方法删除指定图书信息
查询功能实现:
def do_click(): # 触发按钮点击事件之后,获取文本框输入的值 bookname = tx.get() # print(f"被点击了,bookname={bookname}") # messagebox.showinfo("提示", bookname) book = BookDao() res = book.query(("%"+bookname+"%",)) # 清空表格数据 for i in tv.get_children(): tv.delete(i) # 绑定动态数据 for b in res: tv.insert('',END,values=b)
删除功能实现:
def do_delete(): # 如何获取当前Treeview选中行索引 index = tv.selection() # 判断是否选中行 assert len(index) > 0 print(index) # 根据行索引获取数据行 print(tv.item(index)) # 删除选中行 # tv.delete(index) book = BookDao() book.delete(tv.item(index)["values"][0]) # 调用刷新方法 do_click()
新增功能实现:
from tkinter.simpledialog import * def do_add(): bookname = askstring('提示', '请输入书本名称') price = askfloat('提示', '请输入书本价格') booktype = askstring('提示', '请输入书本类型') print(f"bookname={bookname},price={price},booktype={booktype}") # tv.insert('', END, values=(1,bookname, price, booktype)) book = BookDao() book.add((bookname,price,booktype)) # 调用刷新方法 do_click()