本文对总结 Tkinter
环境的准备以及基本控件的使用 1’ 2’ 3’ 4。
使用软件环境: conda 22.9.0
,tk 8.6.11
。
Updated: 2022 / 12 / 20
Python | GUI | Tkinter - 1. 基本控件
5Python | GUI | Tkinter - 2. 组件使用
6Python | GUI | Tkinter - 3. 多窗体
7Python | GUI | Tkinter - 4. 多线程的暂停和继续以及文件间调用
8Python
使用了不同的 GUI
应用程序,这些应用程序在与用户使用的应用程序进行交互时对用户很有帮助。Python
基本上使用 3 个,GUI
、Tkinter
、wxPython
和 PyQt
。所有这些都可以在 Windows
、Linux
和 mac-OS
上运行。但是这些 GUI
应用程序具有许多小部件,即有助于用户与应用程序交互的控件。其中的一些小部件是按钮、列表框、滚动条和树状视图等 9。
Tkinter
(音为 tea-kay-inter
)是 Tk
的 Python
接口,Tk
是 Tcl
/ Tk
的 GUI
工具包。
Tcl
(工具命令语言, 音为 tickle
)是嵌入式应用程序,测试,原型设计和 GUI
开发领域的流行脚本语言。Tk
是一个开源的多平台小部件工具包,许多不同语言都使用它来构建 GUI
程序。而 Tkinter
只是一个使用 Tcl
/ Tk
库的 C
扩展的包装器。什么是 Tcl
? 参考这里 10’ 11’ 12’ 13
Tkinter
的优势, 简单易学(比 Python
的其他 GUI
库简单),跨平台,标准库,无需安装。
GUI
编程的三个核心问题:
tkinter
同其他的比较,比如 PyQt
和 wxPython
,参考这里 14。
安装 python3.8.11
,tk 8.6.11
安装编辑器,演示使用的是 Pycharm
。
使用的系统版本是 macOS Big Sur Version 11.4
。
import tkinter as tk
root = tk.Tk()
# Tk()的作用就是创建一个窗口
如果只是执行以上的两句代码,运行程序是没有反应的,因为只有一个主函数,从上到下执行完就没有了,这个窗口也是很快就消失了,所以现在我们要做的就是让窗口一直显示,那么我们就可以加一个循环
创建的窗口的名字是 root
,那么我们之后使用这个 root
就可以操作这个窗口了。
root.mainloop()
执行以上的3句代码,我们就可以看见窗口了
root.title('窗口标题')
root.geometry("300x100+630+80")
该方法需要传入一个固定格式的字符串,格式 wxh±x±y
其中 w
、h
表示窗口的宽和高
x
、y
表示窗口显示位置的横向和纵向坐标
+
、-
则表示正方向还是负方向,基于屏幕左上角为坐标原点,向下或向右为正方向
注意,当窗口大小不固定时,是通过动态获取根窗口的宽高来计算位置,如果窗口的宽高一开始就是确定的,请使用确定值,尽量避免动态获取窗口的大小,以免影响 GUI
的流畅。
调用 Button()
即可创建这个组件,创建的这个组件我们赋值给一个常量,以后我们就可以用这个常量来操作这个按钮:
btn1 = tk.Button(root)
# 将我们创建的按钮放到这个窗口root上面
btn1["text"] = "点击"
# 给按钮取一个名称为 ‘点击’
btn1.pack()
# 我们创建的按钮组件,已经放到窗口里面了,但是放到窗口的哪个位置,我们就可以用
# pack()去定位(后面会介绍其它定位方法)
创建点击按钮事件的弹窗,先导入messagebox,这个必须单独导入
from tkinter import messagebox
def test(e):
messagebox.showinfo("窗口名称","点击成功")
现在有了按钮,有了方法,我想要做的是一点击按钮,就执行这个方法,那么就需要将按钮和方法进行绑定,按钮组件里面有一个方法 bind()
这个方法就可以实现绑定
btn1.bind("" ,test)
# 第一个参数为:按鼠标左键的事件 第二个参数为:要执行的方法的名字
# 或者
# btn1 = tk.Button(root, text='点击', command=test)
完整代码如下所示:
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
root.title('窗口标题')
root.geometry("300x100+630+80")
btn1 = tk.Button(root)
btn1['text'] = '点击'
btn1.pack()
def test(e):
messagebox.showinfo('窗口名称', '点击成功')
btn1.bind('' , test)
root.mainloop()
所谓布局,就是指控制窗体容器中各个控件(组件)的位置关系。
tkinter
共有3种几何布局管理器,分别是 pack
布局,grid
布局,place
布局。
布局管理器 | 特点 |
---|---|
pack |
要么将组件垂直的排列,要么水平的排列 |
grid |
grid (网格)布局管理器会将控件放置到一个二维的表格里。主控件被分割成一系列的行和列,表格中的每个单元 (cell ) 都可以放置一个控件。grid_info() 可查看组件默认的参数。例如, {'in': |
place |
使用 pack
布局,将向容器中添加组件,第一个添加的组件在最上方,然后是依次向下添加。当 pack
布局不设置属性时,它只会占用能容纳下当前组件的最小空间。
pack
布局区分以下三种空间:
expand
和 fill
属性有什么区别?——
expand
对应的正是要求但未使用的空间,而 fill
对应的是要求并已使用的空间。fill
是填满的意思,将所有要求的空间占满。
选项 | 含义 |
---|---|
fill |
设置组件是否向水平或垂直方向填充。取值可以有 X 、Y 、BOTH 和 NONE 。fill = X (水平方向填充)fill = Y (垂直方向填充)fill = BOTH (水平和垂直)NONE 不填充 |
expand |
设置组件是否展开。取值可以有 YES 、NO(1、0) 。当值为 YES 时,side 选项无效。组件显示在父容器中心位置;若 fill 选项为 BOTH ,则填充父组件的剩余空间。默认为不展开。 |
side |
设置组件的对齐方式。取值可以为左(LEFT )、上(TOP )、右(RIGHT )、下(BOTTOM )。 |
ipadx、ipady |
设置 x 方向(或者 y 方向)内部间隙(子组件之间的间隔),可设置数值,默认是 0 ,非负整数,单位为像素。 |
padx、pady |
设置 x 方向(或者y方向)外部间隙(与之并列的组件之间的间隔)。可设置数值,默认是 0 。非负整数,单位为像素。 |
anchor |
锚选项,当可用空间大于所需求的尺寸时,决定组件被放置于容器的何处。N 、E 、S 、W 、NW 、NE 、SW 、SE 、CENTER (默认值为 CENTER ),表示八个方向以及中心。 |
方法 | 作用 |
---|---|
pack_slaves() |
以列表方式返回本组件的所有子组件对象。 |
pack_configure(option=value) |
给 pack 布局管理器设置属性,使用属性(option )= 取值(value )方式设置 |
propagate(boolean) |
设置为 True 表示父组件的几何大小由子组件决定(默认值),反之则无关。 |
pack_info() |
返回 pack 提供的选项所对应的值。 |
pack_forget() |
Unpack 组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用pack(option, …) ,将其显示。 |
location(x, y) |
x, y 为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1) 表示不在其中 |
size() |
返回组件所包含的单元格,揭示组件大小。 |
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root)
tk.Label(frame, text="Pack 布局的 side 和 fill").pack()
tk.Button(frame, text="A").pack(side=tk.LEFT, fill=tk.Y)
tk.Button(frame, text="B").pack(side=tk.TOP, fill=tk.X)
tk.Button(frame, text="C").pack(side=tk.RIGHT, fill=tk.NONE)
tk.Button(frame, text="D").pack(side=tk.TOP, fill=tk.BOTH)
# 需注意,顶部框架不会展开,也不会填充X或Y方向
frame.pack()
tk.Label(root, text="Pack 布局的 expand").pack()
tk.Button(root, text="我不扩展").pack()
tk.Button(root, text="我不向x方向填充,但我扩展1").pack(expand=1)
tk.Button(root, text="我不向x方向填充,但我扩展5").pack(expand=5)
tk.Button(root, text="我向x方向填充,并且扩展").pack(fill=tk.X, expand=1)
from tkinter import *
root = Tk()
fm1 = Frame(root)
Button(fm1, text='Top').pack(side=TOP, anchor=W, fill=X, expand=YES)
Button(fm1, text='Center').pack(side=TOP, anchor=W, fill=X, expand=YES)
Button(fm1, text='Bottom').pack(side=TOP, anchor=W, fill=X, expand=YES)
fm1.pack(side=LEFT, fill=BOTH, expand=YES)
fm2 = Frame(root)
Button(fm2, text='Left').pack(side=LEFT)
Button(fm2, text='This is the Center button').pack(side=LEFT)
Button(fm2, text='Right').pack(side=LEFT)
fm2.pack(side=LEFT, padx=10)
root.mainloop()
又被称作网格布局,是最被推荐使用的布局。程序大多数都是矩形的界面,我们可以很容易把它划分为一个几行几列的网格,然后根据行号和列号,将组件放置于网格之中。
使用 grid
布局时,需要在里面指定两个参数,分别用 row
表示行,column
表示列。需要注意的是 row
和 column
的序号都从 0
开始,且每个网格只能容纳一个窗口小控件。
要注意,每列的宽度(或每行的高度)由网格中小部件的高度或宽度决定。如果需要额外的设置,只能通过设置网格中的小部件的宽度实现。 另外,可以使用sticky = tk.NSEW
参数使小部件可扩展并填充网格的整个单元格。
在tkinter的官方文档中,并没有给出让 grid
布局适配根窗口拉伸的方法,但是通过查阅 tcl/Tk
的文档,可知设置权重能满足该需求。
比如,
# 第一个参数是想要设置的列/行的序号, 第二个参数是比例
root.grid_columnconfigure(x, weight=1)
root.grid_rowconfigure(x, weight=1)
选项 | 含义 |
---|---|
column |
列号,设置将组件放置于第几列。取值为列的序号,不是列数。 |
columnspan |
跨列,跨越的列数,正整数。 |
row |
行号,设置将组件放置于第几行。取值为行的序号,不是行数。 |
rowspan |
跨行,跨越的行数,正整数。 |
ipadx, ipady |
设置子组件之间的间隔,x 方向或 y 方向,默认单位为像素,非浮点数,默认 0.0 。 |
padx, pady |
与之并列的组件之间的间隔,x 方向或 y 方向,默认单位为像素,非浮点数,默认 0.0 。 |
sticky |
组件紧贴所在的单元格的某一脚,对应于东南西北中以及4个角。东 = e ,南 = s ,西 = w ,北 = n ,ne ,se ,sw , nw ,类似于 pack 布局中的锚选项。sticky=tk.NE 右上角;sticky=tk.SE 右下角; sticky=tk.SW 左下角; sticky=tk.NW 左上角; sticky=tk.N+tk.S 垂直拉伸小控件,并保持水平居中,其等价于字符串值 ns ,以下同; sticky=tk.E+tk.W 水平拉伸且持垂直居中;sticky=tk.N+tk.E+tk.S+tk.W 水平和垂直拉伸,等价于常量 tk.NSEW 和字符串值 nsew sticky=tk.N+tk.S+tk.W 将垂直拉伸并向西(左)对齐 |
column
指定控件所在的列padx
水平方向外边距:pady
垂直方向外边距sticky
组件东南西北的方向row
指定控件所在的行ipadx
水平方向内边距ipady
垂直方向内边距方法 | 作用 |
---|---|
grid_slaves() |
以列表方式返回本组件的所有子组件对象。 |
grid_configure(option=value) |
给 grid 布局管理器设置属性,使用属性(option )= 取值(value )方式设置 |
grid_propagate(boolean) |
设置为 True 表示父组件的几何大小由子组件决定(默认值),反之则无关。 |
grid_info() |
返回 grid 提供的选项所对应的值。 |
grid_forget() |
Unpack 组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用grid(option, …) ,将其显示。 |
grid_location(x, y) |
x, y 为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1) 表示不在其中 |
size() |
返回组件所包含的单元格,揭示组件大小。 |
from tkinter import *
root = Tk()
Label(root, width=15, height=3, bg="red").grid(row=0, column=0)
Label(root, width=15, height=3, bg="green").grid(row=0, column=1)
Label(root, width=15, height=3, bg="blue").grid(row=0, column=2)
Label(root, width=15, height=3, bg="white").grid(row=1, column=0)
Label(root, width=15, height=3, bg="black").grid(row=1, column=1)
Label(root, width=15, height=3, bg="grey").grid(row=1, column=2)
root.mainloop()
如果再加上 root.grid_columnconfigure(x, weight=1)
, root.grid_rowconfigure(x, weight=1)
以确保控件大小根据跟窗口大小自适应放大或者缩小,如下所示:
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
import tkinter as tk
root = tk.Tk()
root.title('Find & Replace')
tk.Label(root, text="Find:").grid(row=0, column=0, sticky='e')
tk.Entry(root, width=60).grid(row=0, column=1, padx=2, pady=2, sticky='we', columnspan=9)
tk.Label(root, text="Replace:").grid(row=1, column=0, sticky='e')
tk.Entry(root).grid(row=1, column=1, padx=2, pady=2, sticky='we', columnspan=9)
tk.Button(root, text="Find").grid(row=0, column=10, sticky='e' + 'w', padx=2, pady=2)
tk.Button(root, text="Find All").grid(row=1, column=10, sticky='e' + 'w', padx=2)
tk.Button(root, text="Replace").grid(row=2, column=10, sticky='e' + 'w', padx=2)
tk.Button(root, text="Replace All").grid(row=3, column=10, sticky='e' + 'w', padx=2)
tk.Checkbutton(root, text='Match whole word only ').grid(row=2, column=1, columnspan=4, sticky='w')
tk.Checkbutton(root, text='Match Case').grid(row=3, column=1, columnspan=4, sticky='w')
tk.Checkbutton(root, text='Wrap around').grid(row=4, column=1, columnspan=4, sticky='w')
tk.Label(root, text="Direction:").grid(row=2, column=6, sticky='w')
tk.Radiobutton(root, text='Up', value=1).grid(row=3, column=6, columnspan=6, sticky='w')
tk.Radiobutton(root, text='Down', value=2).grid(row=3, column=7, columnspan=2, sticky='e')
root.mainloop()
place
布局管理器可以通过坐标精确控制组件的位置,适用于一些布局更加灵活的场景。但是不太推荐使用,因为在不同分辨率下界面往往有较大差异。
选项 | |
---|---|
x , y |
组件左上角的绝对坐标(相当于窗口),整数,默认值 0 。 |
relx ,rely |
组件左上角的坐标(相对于父容器),0~1之间浮点数。相对位置,0.0 表示左边缘(或上边缘),1.0 表示右边缘(或下边缘)。 |
width , height |
组件的宽度和高度,非负整数。 |
relwidth , relheight |
组件的宽度和高度(相对于父容器),0~1之间浮点数。 |
anchor |
锚选项,同 pack 布局,默认值为 NW 。 |
bordermode |
如果设置为 INSIDE ,组件内部的大小和位置是相对的,不包括边框;如果是 OUTSIDE ,组件的外部大小是相对的,包括边框。可以使用常量 INSIDE 、OUTSIDE ,也可以使用字符串形式 inside 、outside |
方法 | 作用 |
---|---|
place_slaves() |
以列表方式返回本组件的所有子组件对象。 |
place_configure(option=value) |
给 place 布局管理器设置属性,使用属性(option )= 取值(value )方式设置 |
place_propagate(boolean) |
设置为 True 表示父组件的几何大小由子组件决定(默认值),反之则无关。 |
place_info() |
返回 place 提供的选项所对应的值。 |
place_forget() |
Unpack 组件,将组件隐藏并且忽略原有设置,对象依旧存在,可以用place(option, …) ,将其显示。 |
place_location(x, y) |
x, y 为以像素为单位的点,函数返回此点是否在单元格中,在哪个单元格中。返回单元格行列坐标,(-1, -1) 表示不在其中 |
size() |
返回组件所包含的单元格,揭示组件大小。 |
import tkinter as tk
root = tk.Tk()
root.title('窗口标题')
root.geometry("300x100+630+80")
btn1 = tk.Button(root)
btn1['text'] = '点击'
btn1.place(relx=0.2, x=10, y=20, relwidth=0.2, relheight=0.5)
btn2 = tk.Button(root)
btn2['text'] = '退出'
btn2.place(relx=0.2, x=70, y=20, relwidth=0.2, relheight=0.5)
btn3 = tk.Button(root)
btn3['text'] = '取消'
btn3.place(relx=0.2, x=130, y=20, relwidth=0.2, relheight=0.5)
root.mainloop()
tkinter
中,每个组件都是一个类,创建某个组件其实就是将这个类实例化。
在实例化的过程中,可以通过构造函数给组件设置一些属性,同时还必须给该组件指定一个父容器,意即该组件放置何处。
最后,还需要给组件设置一个几何管理器(布局管理器),解决了放哪里的问题,还需要解决怎么放的问题,而布局管理器就是解决怎么放问题的,即设置子组件在父容器中的放置位置。
ttk
是Tk 8.5
版本开始加入的模块。在之前,我们学习的小控件外观看起来都很陈旧过时,编写的界面会比较丑陋。而ttk
模块的出现正是为了解决这个问题,它使小控件的外观更接近于系统平台所特定的外观,不仅如此,它还能支持主题的定制,使我们能更简便的改进界面的美观程度。
如果是使用from tkinter import *
方式导包,则只需在其下增加from tkinter.ttk import *
即可应用ttk
风格。使用ttk
模块后,小控件外观会产生差别。
如使用其他方式导包,则需指定ttk
模块控件
控件 | tk 是否支持 |
ttk 是否支持 |
是否在下方给出示意图例 |
---|---|---|---|
Button |
tk |
ttk |
T |
Checkbutton |
tk |
ttk |
T |
Entry |
tk |
ttk |
T |
Frame |
tk |
ttk |
T |
Label |
tk |
ttk |
T |
LabelFrame |
tk |
ttk |
T |
Menubutton |
tk |
ttk |
T |
PanedWindow |
tk |
ttk |
F |
Radiobutton |
tk |
ttk |
T |
Scale |
tk |
ttk |
T |
Scrollbar |
tk |
ttk |
F |
Combobox |
ttk |
F | |
Notebook |
ttk |
F |
import tkinter as tk
from tkinter import ttk
class GUI:
def __init__(self):
self.root = tk.Tk()
self.root.title('title')
self.root.geometry("400x480+500+250")
# self.root.geometry("300x200+500+250")
self.interface()
def interface(self):
""""界面编写位置"""
btntk = tk.Button(self.root, text="Button tk").pack()
btnttk = tk.ttk.Button(self.root, text="Button ttk").pack()
chkbtntk = tk.Checkbutton(self.root, text='Checkbutton tk').pack()
chkbtnttk = ttk.Checkbutton(self.root, text='Checkbutton ttk').pack()
entrytk = tk.Entry(self.root, textvariable='Entry tk')
entrytk.pack()
entrytk.insert(0, 'Entry tk')
entryttk = ttk.Entry(self.root, textvariable='entry ttk')
entryttk.pack()
entryttk.insert(0, 'Entry ttk')
frametk = tk.Frame(self.root, bg='khaki', width=150, height=20).pack()
s = ttk.Style()
s.configure('new.TFrame', background='red')
framettk = ttk.Frame(self.root, style='new.TFrame').pack()
labeltk = tk.Label(self.root, text='Label tk').pack()
labelttk = ttk.Label(self.root, text='Label ttk').pack()
labelframetk = tk.LabelFrame(self.root, text="LabelFrame tk").pack()
tk.Message(labelframetk, text="Today is 14th Aug, 2022.", bg="light blue").pack()
labelframettk = ttk.LabelFrame(self.root, text="LabelFrame ttk").pack()
tk.Message(labelframettk, text="Today is 14th Aug, 2022.", bg="light pink").pack()
Menubuttontk = tk.Menubutton(self.root, text='Menubutton tk')
Menubuttontk.pack()
filemenutk = tk.Menu(Menubuttontk, tearoff=False)
filemenutk.add_checkbutton(label="打开", command=self.callback, selectcolor="yellow")
filemenutk.add_command(label="保存", command=self.callback)
filemenutk.add_separator()
filemenutk.add_command(label="退出", command=self.root.quit)
Menubuttontk.config(menu=filemenutk)
Menubuttonttk = ttk.Menubutton(self.root, text='Menubutton ttk')
Menubuttonttk.pack()
filemenuttk = tk.Menu(Menubuttontk, tearoff=False)
filemenuttk.add_checkbutton(label="打开", command=self.callback, selectcolor="blue")
filemenuttk.add_command(label="保存", command=self.callback)
filemenuttk.add_separator()
filemenuttk.add_command(label="退出", command=self.root.quit)
Menubuttonttk.config(menu=filemenuttk)
rdbtntk = tk.Radiobutton(self.root, text="Radiobutton tk").pack()
rdbtnttk = ttk.Radiobutton(self.root, text="Radiobutton ttk").pack()
scaletk = tk.Scale(self.root, orient='horizonta', from_=0, to=100, length=100).pack()
scalettk = ttk.Scale(self.root, orient='horizonta', from_=0, to=100, length=100).pack()
def callback(self):
print('called back ~')
if __name__ == '__main__':
gui = GUI()
gui.root.mainloop()
在使用 ttk
控件时,会发现它的控件不支持 bg
、fg
、border
这样涉及样式的属性,这是因为它对外观样式进行了重新定义。
ttk
对外观样式的抽象共有三个级别:
style = ttk.Style()
stype
的引用方式如上,
style.theme_names()
('aqua', 'clam', 'alt', 'default', 'classic')
style.theme_use()
aqua
style.theme_use("classic")
在 ttk
中,控件实际上是一个字符串,要改变控件样式,需要指定这个字符串名称,而不是类名,它们的对应关系如下:
类名 | 控件样式名 |
---|---|
Button |
TButton |
Checkbutton |
TCheckbutton |
Combobox |
TCombobox |
Entry |
TEntry |
Frame |
TFrame |
Label |
TLabel |
LabelFrame |
TLabelFrame |
Menubutton |
TMenubutton |
Notebook |
TNotebook |
PanedWindow |
TPanedwindow |
Progressbar |
Horizontal.TProgressbar 或 Vertical.TProgressbar |
Radiobutton |
TRadiobutton |
Scale |
Horizontal.TScale 或 Vertical.TScale |
Scrollbar |
Horizontal.TScrollbar 或 Vertical.TScrollbar |
Separator |
TSeparator |
Sizegrip |
TSizegrip |
Treeview |
Treeview |
需要注意,在创建新样式时,应当定义 newName.oldName
形式的名称
import tkinter
from tkinter import Tk
from tkinter import ttk
root = Tk()
style = ttk.Style()
# 定义一个全局样式作为默认样式("."表示此样式将应用于顶级窗口及其所有子元素)
style.configure('.', font='Arial 14', foreground='brown', background='yellow')
# 未指定样式时,使用全局默认样式
ttk.Label(root, text='我没有指定样式').pack()
# 定义一个名为danger的新样式(newName.oldName格式)
style.configure('danger.TButton', font='Times 12', foreground='red', padding=1)
ttk.Button(root, text='我使用danger样式', style='danger.TButton').pack()
# 为小控件的不同状态指定样式
style.map("new_state_style.TButton", foreground=[('pressed', 'red'), ('active', 'blue')])
ttk.Button(text="不同状态不同样式", style="new_state_style.TButton").pack()
# 覆盖Entry的当前主题(即使没有指定样式,也会受到主题更改的影响)
current_theme = style.theme_use()
style.theme_settings(current_theme,
{"TEntry": {
"configure": {"padding": 10},
"map": {"foreground": [("focus", "red")]}}})
val = tkinter.StringVar()
val.set('Entry控件样式')
ttk.Entry(textvariable=val).pack()
root.mainloop()
import tkinter as tk
from tkinter import ttk -下拉选择框
class GUI:
def __init__(self):
self.root = tk.Tk()
self.root.title('窗口标题')
self.root.geometry("400x250+500+250")
self.interface()
def interface(self):
""""界面编写位置"""
pass
if __name__ == '__main__':
gui = GUI()
gui.root.mainloop()
?
控件类 | 名称 | 简要说明 |
---|---|---|
Label |
标签 | |
LabelFrame |
标签框架 | 带有标签和边框的一个容器,通常用于控件分组 |
Message |
消息框 | 类似于标签,但可以自动换行,用于显示多行文本 |
OptionMenu |
选项菜单 | 下拉菜单 |
Spinbox |
输入控件 | 与Entry类似,但可以指定输入范围值 |
Menu |
菜单 | 点菜单按钮后弹出的一个选项列表,用户可以从中选择 |
Listbox |
列表框 | 一个选项列表,用户可以从中选择 |
Scrollbar |
滚动条 | 对其支持的组件(文本域、画布、列表框、文本框)提供滚动功能 |
Text |
多行文本框 | 显示多行文本 |
Top Level |
顶级窗口 | 独立存在的窗口 |
Label
作为一个最常用的控件,主要用实现显示功能,能够展示一些文本或者图片或者文本和图片的组合使用 16。
它的语法格式:
Label(父对象, options, ...)
参数 | 含义 | |
---|---|---|
父对象 | 表示这个文本框将建立在哪一个窗口内 | |
options |
可选项,即该按钮的可设置的属性。这些选项可以用键 =值的形式设置,并以逗号分隔 | |
font(,) |
font=('', 15) ,表示字体、字号 |
|
text |
标签内容 | |
bg |
背景色 | |
fg |
前景色 |
def interface(self):
""""界面编写位置"""
content = "汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。\n" \
"天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。"
lf1 = tk.LabelFrame(self.root, text="LabelFrame Top").pack()
tk.Label(lf1, text=content, bg="orange").pack()
lf2 = tk.LabelFrame(self.root, text="LabelFrame Bottom").pack()
tk.Message(lf2, text=content, bg="light blue").pack()
参考此处 17
def interface(self):
""""界面编写位置"""
LIST = ["选项1", "选项2", "选项3"]
val = tk.StringVar()
val.set(list[0])
# 注意,传入的列表前需要加一个*号,这是表示不定参的传递,
# 两个*则是表示字典类型的不定参传递
tk.OptionMenu(self.root, val, *LIST).pack()
参考这里 18
def interface(self):
""""界面编写位置"""
# 指定数字范围
var_range = tk.StringVar()
var_range.set(0)
tk.Spinbox(self.root, textvariable=var_range, from_=-5, to=5).pack()
# 指定列表范围
LIST = ["选项1", "选项2", "选项3"]
tk.Spinbox(self.root, value=LIST).pack()
略, 可参考 19
在使用 Tkinter
进行 GUI
编程的过程中,如果需要用户自己进行选择时就可以使用列表框控件。
列表框中的选项可以是多个条目,也可以是单个唯一条目,但常用于多个条目 20’ 21。
参数 | 含义 | |
---|---|---|
listvariable |
1. 指向一个 StringVar 类型的变量,该变量存放 Listbox 中所有的项目 2. 在 StringVar 类型的变量中,用空格分隔每个项目,例如 var.set("c c++ java python") |
|
selectbackground |
1. 指定当某个项目被选中的时候背景颜色,默认值由系统指定 | |
selectborderwidth |
1. 指定当某个项目被选中的时候边框的宽度 2. 默认是由 selectbackground 指定的颜色填充,没有边框3. 如果设置了此选项, Listbox 的每一项会相应变大,被选中项为 raised 样式 |
|
selectforeground |
1. 指定当某个项目被选中的时候文本颜色,默认值由系统指定 | |
selectmode |
1. 决定选择的模式,tk 提供了四种不同的选择模式,分别是 single (单选)、browse (也是单选,但拖动鼠标或通过方向键可以直接改变选项)、multiple (多选)和 extended (也是多选,但需要同时按住 Shift 键或 Ctrl 键或拖拽鼠标实现)。默认是 browse |
|
setgrid |
指定一个布尔类型的值,决定是否启用网格控制,默认值是 False |
|
takefocus |
指定该组件是否接受输入焦点(用户可以通过 tab 键将焦点转移上来),默认值是 True |
|
xscrollcommand |
为 Listbox 组件添加一条水平滚动条,将此选项与 Scrollbar 组件相关联即可。列表框横向滚动时的回调监听。 |
|
yscrollcommand |
为 Listbox 组件添加一条垂直滚动条,将此选项与 Scrollbar 组件相关联即可。列表框纵向滚动时的回调监听,该属性的值是一个回调函数。 |
方法 | 作用 |
---|---|
activate(index) |
将给定索引号对应的选项激活,即文本下方画一条下划线 |
bbox(index) |
返回给定索引号对应的选项的边框,返回值是一个以像素为单位的 4 元祖表示边框:(xoffset , yoffset , width , height ), xoffset 和 yoffset 表示距离左上角的偏移位置 |
curselection() |
返回一个元组,包含被选中的选项序号(从 0 开始) |
delete(first, last=None) |
删除参数 first 到 last 范围内(包含 first 和 last )的所有选项 |
get(first, last=None) |
返回一个元组,包含参数 first 到 last 范围内(包含 first 和 last )的所有选项的文本 |
index(index) |
返回与 index 参数相应选项的序号 |
itemcget(index, option) |
获得 index 参数指定的项目对应的选项(由 option 参数指定) |
itemconfig(index, **options) |
设置 index 参数指定的项目对应的选项(由可变参数 **option 指定) |
nearest(y) |
返回与给定参数 y 在垂直坐标上最接近的项目的序号 |
selection_set(first, last=None) |
设置参数 first 到 last 范围内(包含 first 和 last )选项为选中状态,使用 selection_includes (序号) 可以判断选项是否被选中。 |
size() |
返回 Listbox 组件中选项的数量 |
xview(*args) |
该方法用于在水平方向上滚动 Listbox 组件的内容,一般通过绑定 Scollbar 组件的 command 选项来实现。 如果第一个参数是 moveto ,则第二个参数表示滚动到指定的位置:0.0 表示最左端,1.0 表示最右端;如果第一个参数是 scroll ,则第二个参数表示滚动的数量,第三个参数表示滚动的单位(可以是 units 或 pages ),例如 xview( scroll, 2, pages`)表示向右滚动二行。 |
yview(*args) |
该方法用于在垂直方向上滚动 Listbox 组件的内容,一般通过绑定 Scollbar 组件的 command 选项来实现 |
参考此处 22
def interface(self):
""""界面编写位置"""
self.varListbox = tk.StringVar()
self.varListbox.set(["Go", "Python", "Java", "Dart", "JavaScript"])
self.listbox = tk.Listbox(self.root, listvariable=self.varListbox, selectmode=tk.BROWSE)
self.listbox.pack(padx=10, pady=10)
self.listbox.bind("<>" , self.show)
self.varLabel = tk.StringVar()
label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
label.pack()
def show(self, event):
self.varLabel.set(self.listbox.get(self.listbox.curselection()))
参考此处 23’ 24
def interface(self):
""""界面编写位置"""
self.varListbox = tk.StringVar()
self.varListbox.set(["Go", "Python", "Java", "Dart", "JavaScript"])
self.listbox = tk.Listbox(self.root, listvariable=self.varListbox, selectmode=tk.EXTENDED)
self.listbox.pack(padx=10, pady=10)
self.listbox.bind("<>" , self.show)
self.varLabel = tk.StringVar()
self.label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
self.label.pack()
def show(self, event):
content = []
for i in self.listbox.curselection():
content.append(self.listbox.get(i))
self.varLabel.set(content)
运行效果如下:
列表框通常用于数据展示或者作为选项菜单使用。滚动条则是一种辅助的小控件,它通常与列表框或者多行文本框结合使用 21。
def interface(self):
""""界面编写位置"""
self.varListbox = tk.StringVar()
self.varListbox.set(["Go", "Python", "Java", "Dart", "JavaScript", "C", "C++", "PHPHPHPHPHPHPHPHPHPHPHP"])
# 分别创建x方向、y方向的两个滚动条。orient属性设置其滚动方向
y_bar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
x_bar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
# 创建列表框
self.listbox = tk.Listbox(self.root,
yscrollcommand=y_bar.set,
xscrollcommand=x_bar.set,
listvariable=self.varListbox,
height=5)
y_bar['command'] = self.listbox.yview
y_bar.pack(side=tk.RIGHT, fill=tk.Y)
x_bar['command'] = self.listbox.xview
x_bar.pack(side=tk.BOTTOM, fill=tk.X)
self.listbox.pack(anchor=tk.NW, fill=tk.BOTH, expand=tk.YES)
bt = tk.Button(self.root, text='删除', command=lambda x=self.listbox: x.delete(tk.ACTIVE)) # 使用匿名函数,创建删除函数,点击删除按钮,会删除选项
bt.pack(side=tk.BOTTOM)
一个简单的按钮,用来响应用户的一个点击操作。能够与一个函数关联,当按钮被按下时,自动调用该函数。
它的属性可以直接参考标签,事实上按钮就是一个特殊的标签,只不过按钮多出了点击响应的功能。
参数 | 含义 | |
---|---|---|
text |
字符串,按钮的文本内容 | |
activebackground |
当鼠标放上去时,按钮的背景色 | |
activeforeground |
当鼠标放上去时,按钮的前景色 | |
bd(bordwidth) |
单位为像素,默认值为 2 个像素 按钮边框的大小 |
|
bg(background) |
按钮的背景色 | |
command |
函数名的字符串形式 按钮关联的函数,当按钮被点击时,执行该函数 | |
fg(foreground) |
按钮的前景色(按钮文本的颜色) | |
font |
设置字体,还包含样式和大小 | |
image |
给按钮设置一张图像,必须是用图像 create 方法产生的 |
|
bitmap |
指定按钮显示一张位图 | |
justify |
LEFT 、CENTER 、RIGHT |
显示多行文本的时候,设置不同行之间的对齐方式 |
padx |
单位像素 按钮在 x 轴方向上的内边距,是指按钮的内容与按钮边缘的距离 |
|
pady |
单位像素 按钮在 y 轴方向上的内边距 |
|
relief |
RAISED , SUNKEN , FLAT , RIDGE , SOLID , GROOVE |
设置控件 3D 效果 |
state |
DISABLED 、ACTIVE 、NORMAL 设置组件状态。正常 (normal )、激活(active )、禁用(disabled ) |
|
underline |
取值为整数,默认值为 -1 |
默认按钮上的文本都不带下划线。取值就是带下划线的字符串索引,为 0 时,第一个字符带下划线,为 1 时,前两个字符带下划线,以此类推 |
width |
单位像素, 按钮的宽度,如未设置此项,其大小以适应按钮的内容(文本或图片的大小) | |
height |
单位像素. 按钮的高度,同 width 属性 |
|
wraplength |
取值为整数,默认值 0 , 限制按钮每行显示的字符的数量 |
|
textvariable |
指定一个变量名,变量值被转变为字符串在控件上显示。当变量值改变,控件也将自动更新 | |
anchor |
取值可参考布局中的锚选项 锚选项,控制文本的位置,默认为中心 |
def interface(self):
""""界面编写位置"""
self.Button0 = tk.Button(self.root, text="按钮显示")
self.Button0.grid(row=0, column=0)
所谓的文本框 Entry
,通常是指单行的文本框,在 GUI
程序设计中,这是用于输入的最基本控件,我们可以使用它输入或显示单行字符串,自带宽高 25,通常不需要设定高度,但是存在一些方法可以设定其高度和宽度 26 。
如果所输入的字符串长度大于文本框的宽度,所输入的文字会自动隐藏,造成部分内容无法显示,碰到这种状况时可以使用箭头键移动鼠标光标到看不到的区域。
文本框限定的是单行文字 27,如果想要处理多行文字,需要使用控件中的 Text
。
它的语法格式:
Entry(父对象, options, ...)
参数 | 含义 | |
---|---|---|
父对象 | 表示这个文本框将建立在哪一个窗口内 | |
options |
borderwidth |
边界宽度,默认是两个像素 |
bd |
边界宽度,默认是两个像素 | |
background |
背景色彩 | |
bg |
背景色彩 | |
command |
当用户更改内容时,会自动执行此函数 | |
cursor |
当鼠标光标移至按钮上时的形状 | |
exportselection |
如果执行选取时,所选取的字符串会自动输出至剪贴板; 如果想要避免,可以设置 exportselection=0 |
|
foreground |
前景色彩 | |
fg |
前景色彩 | |
font |
字形 | |
height |
高,单位是字符高 | |
highlightbackground |
当功能按钮获取焦点时的背景颜色 | |
highlightcolor |
当工人按钮取得焦点时的颜色 | |
justify |
当有多行文字时,最后一行文字的对齐方式 | |
relief |
可由此控制文字外框, 默认是 relief=FLAT |
|
selectbackground |
被选取字符串的背景色彩 | |
selectborderwidth |
选取字符串时的边界宽度,预设是1 | |
selectfroeground |
被选取字符串的前景色彩 | |
show |
显示输入字符。 例如, show=* 表示显示星号,常用于输入密码字段 |
|
state |
输入状态。默认是 NORMAL 表示可以输入,DISABLE 则表示无法输入 |
|
textvariable |
文字变量 | |
width |
宽,单位是字符宽 | |
xscrollcommand |
在 X 轴使用滚动条 |
参考这里 3
方法 | 作用 |
---|---|
delete( first, last=None) |
删除字符的部件,在指标之一,但不包括在最后位置的字符开始。 如果第二个参数被忽略,只有在单个字符的位置被删除。 |
get() |
返回当前组件的字符串 |
icursor(index) |
在给定索引处的字符之前插入光标。 |
index(index) |
移动 entry 的内容,使得给定索引处的字符是最左边的可见字符。 如果文本在 entry 中刚好完全显示,则不起作用。 |
insert ( index, s ) |
将字符串 s 插入给定索引处的字符之前。 |
select_adjust(index) |
此方法用于确保选中的部分包含指定索引处的字符。 |
select_clear() |
清除选中的。 如果当前没有选中的,则不起作用。 |
select_from(index) |
将 ANCHOR 索引位置设置为由索引选择的字符位置,并选择该字符。 |
select_present() |
如果有选择,则返回 true ,否则返回 false 。 |
select_range(start, end) |
在程序控制下设置选择。 选择从开始索引处开始的文本,但不包括结束索引处的字符。 起始位置必须在结束位置之前。 |
select_to(index) |
选择从 ANCHOR 位置开始的所有文本,但不包括给定索引处的字符。 |
xview(index) |
此方法在将 Entry 链接到水平滚动条时非常有用。 |
xview_scroll(number, what) |
用于水平滚动 Entry 。参数必须是 UNITS ,按字符宽度滚动,或者按页面大小来滚动。数字是从左到右滚动的正数,负数从右到左滚动。 |
tk.Entry(root, width)
Entry
控制元件中的 width
选项设定宽度, 其单位是文字单位,而不是像素。0
的宽度。tk.Entry().place(width, height)
place
方法中的 width
和 height
选项设定 Entry
控制元件的宽度和高度像素单位tk.Entry().place(ipadx, ipady)
tk.Entry().grid(ipadx, ipady)
pack
和 grid
方法中的 ipadx
和 ipady
在水平和垂直方向上设定内部填充,可以间接设定 Entry
控制元件的宽度和高度。
Entry
的实际宽度是 2 * ipadx + 预设 Entry 宽度
,类似地,Entry
的实际宽度是 2 * ipady + 预设 Entry 高度
。
def interface(self):
""""界面编写位置"""
self.Entry0 = tk.Entry(self.root)
self.Entry0.grid(row=0, column=0)
多行文字区域,可用来收集(或显示)用户输入的文字,可以编辑文本格式,改变文本框的宽高 25。
也可以当网页浏览器使用,插入文字、图片、组件等。
Text
组件创建方法为 Text(父组件,参数)
。
可以使用默认的参数来创建一个 Text
组件,比如 text = tk.Text(root)
,或者,text=Text(root, width=12, height=5)
,宽 12
个字符,高 5
行字符。
参数 | 含义 |
---|---|
autoseparators |
是否自动插入一个分隔符,默认 True |
background 或 bg |
组件的背景颜色 |
borderwidth 或 bd |
组件的边框宽度 |
cursor |
鼠标光标样式 |
exportselection |
选中的文本是否可以被复制到剪贴板,默认 True |
font |
组件的默认文本字体 |
foreground 或 fg |
组件的前景色,字体颜色 |
height |
Text 组件的高度,单位是:行 |
highlightabckground |
组件没有焦点时的高亮边框的颜色 |
highlightcolor |
组件有焦点时的高亮边框的颜色 |
highlightthickness |
高亮边框的宽度 |
insertbackground |
插入光标的颜色,默认为 black |
insertborderwidth |
插入光标的边框宽度 ,默认为 0 |
insertontime |
插入光标闪烁的间隔时间,单位:毫秒 |
insertwidth |
光标的宽度,默认为 2 像素 |
maxundo |
最大的‘撤销’操作次数,默认为 0 ,为 -1 表示不限制 |
padx |
水平方向上内容与边框之间的间距,默认为 1 |
pady |
垂直方向上内容与边框之间的间距,默认为 1 |
relief |
组件边框样式 |
selectbackground |
选中文本的背景颜色 |
selectborderwidth |
选中文本的边框宽度 |
selectforeground |
选中文本的字体颜色 |
setgrid |
是否启用网格控制,默认为 False |
spacing1 |
每一行的上面间距,如有折行,只在第一行起作用 28 |
spacing2 |
折行之间的行间距 28 |
spacing3 |
每一行的下面间距,如有折行,只在最后一行起作用 28 |
state |
组件的状态 NORMAL 和 DISABLED |
tabs |
定义按 Tab 键的移动距离 |
takefocus |
是否可以使用 Tab 键将焦点转移到本组件 |
undo |
开启 undo / redo 功能 |
width |
组件的宽度,单位是:字符数 |
wrap |
决定文本长度超过组件宽度如何换行:NONE 不换行CHAR 按字符来换行,中英文都一样。WORD 按单词自动换行,保证英文单词做为一个整体来换行,对中文没有什么意义。 |
xscrollcommand |
与滚动条组件在水平方向相关联 |
yscrollcommand |
与滚动条组件在垂直方向相关联 |
方法 | 作用 |
---|---|
delete |
语法是 delete(开始位置,结束位置) ,如果只有1个参数,就只删除一个字符; 有2个参数,则删除一段文本 28。 |
get |
获取所选的字符内容,语法是 get(开始位置,结果位置) 。位置可以直接用行、列格式,也可以用位置表达式来表示 28。 |
INSERT |
等价于字符串 insert ,表示当前光标的位, 可以将字符插入到指定的位置,语法是 insert(插入位置,插入字符) 举例 28: insert(END, '汽车') ,在字符串末尾插入字符insert(INSERT, ‘汽车') ,在光标处插入字符insert(2.3, '飞机') ,在第2 行、第3 列处插入字符注:行从 1 开始起步,列从 0 列开始起步。位置表达式的用法参考这里 28 |
CURRENT |
等价于字符串 current ,当前鼠标所在的位置 |
END |
等价于字符串 end ,表示文本最末的位置 |
line.column |
直接指定行列位置,如 1.0 ,表示第一行第一列,注意,行号从 1 开始,列号从 0 开始。 |
line.end |
指定行末位置,如 1.end ,表示第一行结尾的位置 |
+ n chars |
如 1.0+5c ,表示在第一行第一列的位置向右移动五个字符的位置 |
linestart |
如 current linestart ,表示当前光标所在行的行首位置 |
Mark |
主要用来控制位置 |
Tags |
主要用来改变内容的样式 |
Text
组件跟 Entry
,Lable
等组件在字体方面可不一样,其它字体只要设置一种字体,而 Text
组件可以为同一组件内的不同的字符设置为不同的字体,颜色,大小。
当我们为 Text
组件内的一两个字符或一段字符取一个名字时,这个名字就是一个标签。说白了,标签就是你选定一段字符的名称。
书签是
行.列
位置的另一个名称,是一个位置;
标签是一段选定的字符的名称,是一段字符。
可以为 Text
组件创建标签,也可以删除标签,也可以为标签设置一下,如为标签设置字体,颜色等,设置成功后,这个标签代表的一段字符就会表现出设置好的字体和颜色。
系统内有一个内置的标签,那就是 SEL
,SEL
就是你用鼠标选中的一段字符的标签。
当我们用鼠标选定文本框中的某一段文本时,这一段文本就是 SEL
标签的范围,默认情况是,选定的文本是蓝色背景,白色文字,我们可以用代码为 SEL
标签改变一为红色背景,白色文字,同时也可以改变字体大小等。见示例。
下面是标签的一些常用的方法:
方法 | 作用 |
---|---|
tag_add(标签名,开始位置,结束位置) |
为开始位置和结束位置之间的字符创建一个标签名。 |
tag_config(标签名,参数……) |
为标签设置字体,颜色等等各种参数。 |
tag_delete(标签名) |
标签被删除,与此标签相关的设置显示效果都自动取消 |
tag_remove(标签名) |
标签被删除,但此标签相关的设置显示效果还起作用。 |
tag_bind(标签名,绑定事件,调用的函数) |
设置标签后,这个标签还可以绑定事件。比如,写一个网址,你点击它就可以用默认的浏览器打开它。 |
一个多选框组件。主要给用户提供多个选项的选中功能。
Checkbutton(master,option,...)
参考这里 3
方法 | 作用 |
---|---|
deselect() |
清除单选按钮的状态。 |
flash() |
在激活状态颜色和正常颜色之间闪烁几次单选按钮,但保持它开始时的状态。 |
invoke() |
可以调用此方法来获得与用户单击单选按钮以更改其状态时发生的操作相同的操作。 |
invoke() |
设置单选按钮为选中。 |
select() |
设置单选按钮为选中。 |
def interface(self):
""""界面编写位置"""
self.Checkbutton01 = tk.Checkbutton(self.root, text="名称")
self.Checkbutton01.grid(row=0, column=2)
单选按钮,即在同一组内只能有一个按钮被选中,每当选中组内的一个按钮时,其它的按钮自动改为非选中态,与其他控件不同的是,它有组的概念。
Radiobutton(parent, option, ... )
参考这里 3
方法 | 作用 |
---|---|
deselect() |
清除单选按钮的状态。 |
def interface(self):
""""界面编写位置"""
self.varRbtn = tk.StringVar()
self.Rbtn1 = tk.Radiobutton(self.root, text="Option 1", variable=self.varRbtn, value='Beijing', command=self.show).pack()
self.Rbtn2 = tk.Radiobutton(self.root, text="Option 2", variable=self.varRbtn, value='Shanghai', command=self.show).pack()
self.Rbtn3 = tk.Radiobutton(self.root, text="Option 3", variable=self.varRbtn, value='Guangzhou', command=self.show).pack()
self.varLabel = tk.StringVar()
label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
label.pack()
def show(self):
self.varLabel.set(self.varRbtn.get())
参考这里 29’ 30
Combobox
是下拉框控件,可以看成是单行文本框组件 Entry
和 下拉菜单组建构成的。所以在文本框里,可以输入,在菜单里也可以选择。
当点击下拉按钮之后,会弹出下拉列表,用户选择相应的选项后,下拉列表会收起,用户选择的选项会出现在输入框中。
下拉框控件和列表框控件非常类似,不过只显示为一个输入框,更省窗口空间 30。
Combobox
不是定义在 tkinter
中的控件,而是定义在 ttk
中的一个控件。
Combobox
不是继承的 Widget
类,而是继承了 Entry
类,因此可以把 Combobox
当成是 Entry
类的扩展。
它的语法格式:
Combobox(父对象, options, ...)
参数 | 含义 | |
---|---|---|
父对象 | 表示这个文本框将建立在哪一个窗口内 | |
options |
height |
高度,下拉显示的条目数量,默认值是20。 如果超过这个默认值,会自动出现滚动条。如果项目数没有到 height 设定的值,会显示实际的行数。也就是说不会出现空白行,比如行数是 10 ,就不会出现 10 个待选项 + 10 个空白行的情况,下拉列表只显示 10 个待选项。 |
width |
定义输入框的宽度。默认值是 20 。注意,这个参数只能调整输入框的宽度,不能调整下拉按钮的宽度。在计算真个下拉框控件的宽度的时候,要把这两个数值加在一起。 |
|
state |
设置状态 normal (可选可输入)、readonly (只可选)、 disabled (禁止输入选择) |
|
cursor |
鼠标位于Combobox控件时的形状, 比如 arrow , circle , cross , plus … |
|
font(,) |
font=('', 15) ,表示字体、字号 |
|
textvariable |
通过 StringVar 设置可改变的值 |
|
value |
以元组方式存在,设置下拉框的选项。该参数可以动态调整。 | |
justify |
输入框中的文字对齐方式。只有当文本内容的长度小于输入框框的长度才有效。默认是左对齐 tk.LEFT 。其他的2个对齐方式是 tk.CENTER (居中)和 tk.RIGHT (右对齐)。 |
|
postcommand |
下拉列表弹出前的回调函数。用于动态改变下拉列表内容,即即时输出选择前的选项值。 要即时得到选择后的选项值,要借助一个虚拟事件 < 即时得到 combobox 选择后的值 31。 |
|
takefocus |
设置能否使用Tab键获得输入焦点。默认是True。 | |
style |
ttk 中的控件,没有了设置背景色、前景色等属性,所有的这些都通过style来设置。 |
|
validate validatecommand |
设置验证回调函数,用以验证输入框中的内容是否符合要求。 |
参考这里 30
方法 | 作用 |
---|---|
current(newindex=None) |
没有任何参数,返回输入框中的内容在下拉列表中的行号。 如果输入框中的内容不与下拉列表中的任何一项相匹配,返回 -1 ; 如果有参数,返回索引所代表的行的内容,该选项会出现在输入框中。不返回任何参数。 |
set(value) |
设置输入框中的文本。调用该函数后,在输入框显示 value 指定的值。注意,value 可以不是下拉列表中的值。我们可以用绑定的变量,如 var.set (文本值 ) 来设置 combobox 组件上的 textvariable (输入文本 )。此外,还有另外一种方法 com1.set (文本值 ) 达到的效果是一样的。 |
def interface(self):
""""界面编写位置"""
cb = tk.ttk.Combobox(master=self.root,
height=10,
width=20,
state='normal',
cursor='arrow',
font=('', 15),
value=('python', 'java', 'C', 'C++'))
# 若是选项很多,可以使用独立在Combobox()外来处理,如下所示:
# combobox
# cb['values'] = ('python', 'java', 'C', 'C++')
cb.pack(padx=5, pady=10)
一个滑块控件。用于在一个范围内,拖动它改变值的大小,例如音量条。
它的语法格式:
Scale(父对象, options, ...)
参数 | 含义 | |
---|---|---|
父对象 | 表示这个文本框将建立在哪一个窗口内 | |
options |
from_ |
设置最小值 |
to |
设置最大值 | |
tickinterval |
设置刻度 | |
length |
设置滑块的长度,单位为像素 |
更多的示例可以参考这里 32
def interface(self):
""""界面编写位置"""
self.var = tk.IntVar()
self.scale = tk.Scale(self.root, orient='horizonta', variable=self.var,
from_=0, to=200, tickinterval=50, length=200, command=self.show).pack()
self.varLabel = tk.StringVar()
label = tk.Label(self.root, textvariable=self.varLabel, width=20, height=1, bg='lightblue', fg='red')
label.pack()
def show(self, event):
self.varLabel.set(self.var.get())
PanedWindow
是一个窗口布局管理的插件,可以包含一个或者多个子控件。用户可以用鼠标移动上面的分割线来改变每个子控件的大小 33。
PanedWindow
可以用来创建2格或者3格的布局。
下面的例子演示了如何使用 tk
的 PanedWindow
插件创建窗格:
def interface(self):
""""界面编写位置"""
panedwindowtk = tk.PanedWindow(orient=tk.VERTICAL)
panedwindowtk.pack(fill=tk.BOTH, expand=1)
top = tk.Label(panedwindowtk, text="top pane", bg='yellow', width=10, height=5)
panedwindowtk.add(top)
bottom = tk.Label(panedwindowtk, text="bottom pane", bg='light blue', width=10, height=5)
panedwindowtk.add(bottom)
def interface(self):
""""界面编写位置"""
panedwindowtk = tk.PanedWindow()
panedwindowtk.pack(fill=tk.BOTH, expand=1)
left = tk.Label(panedwindowtk, text="left pane", bg='yellow', width=10, height=5)
panedwindowtk.add(left)
panedwindow2tk = tk.PanedWindow(panedwindowtk, orient=tk.VERTICAL)
panedwindowtk.add(panedwindow2tk)
top = tk.Label(panedwindow2tk, text="top pane", bg='light blue', width=5, height=5)
panedwindow2tk.add(top)
bottom = tk.Label(panedwindow2tk, text="bottom pane", bg='pink', width=5, height=5)
panedwindow2tk.add(bottom)
实际上我们的根窗口就是一个顶级窗口。
它是独立存在的一个窗口,当我们需要编写多窗口程序或者自定义对话框时,就需要使用它。
既然根窗口也是一个顶级窗口,那么顶级窗口的属性和方法,根窗口同样具有。
def interface(self):
""""界面编写位置"""
self.btn = tk.Button(self.root, text="打开窗口", command=self.onclick).pack()
def onclick(self):
window = tk.Toplevel()
window.geometry('200x100+500+250')
label = tk.Label(window, text="我是新窗口").pack()
window.transient(self.root)
# 设置它所依托的父窗口
window.mainloop()
# 必须调用mainloop,打开一个新窗口后,需要进入新窗口的事件循环
def interface(self):
btnOpen = tk.Button(self.root, text="打开窗口", command=self.onclick).pack()
def onclick(self):
window = tk.Toplevel()
window.geometry('200x100+500+250')
window.title('我是新窗口')
btnClick = tk.Button(window, text="点击", command=lambda: self.test(window)).pack()
window.mainloop()
def test(self, window):
window.iconify()
window.deiconify()
如果要使该窗口保持在所有其他窗口之上 34’ 35:
root.attributes("-topmost", True)
# 其中root是您的顶级或Tk。 不要忘记"topmost"前面的 -
进度条控件
它的语法格式:
Progressbar(父对象, options, ...)
参数 | 含义 | |
---|---|---|
options |
mode |
有两个值可选。indeterminate 表示来回反弹样式,determinate 表示步进样式 |
length |
设置进度条的长度 |
方法 | 说明 |
---|---|
.start() |
开始自动增长模式 |
.stop() |
停止自动增长模式 |
.step(amount) |
默认起始步长 (?) |
.grid_forget() .place_forget() |
取决于 Progressbar 的位置置放使用的是 grid 布局方法还是 place 布局方法,选择相应的 forget 方法来删除 Progressbar 控件 36。详情查看 grid 、place 布局管理方法。 |
def interface(self):
""""界面编写位置"""
self.progress = ttk.Progressbar(self.root, mode='indeterminate', length=100)
# 创建进度条控件
self.progress.pack(pady=10, padx=10)
# 启动进度条控件
self.progress2 = ttk.Progressbar(self.root, mode='determinate', length=100)
self.progress2.pack(pady=10, padx=10)
tk.Button(self.root, text='Start', command=self.start).pack()
tk.Button(self.root, text='Stop', command=self.stop).pack()
tk.Button(self.root, text='Delete', command=self.delete).pack()
def start(self):
self.progress.start(interval=100)
self.progress2.start(interval=20)
def stop(self):
self.progress.stop()
self.progress2.stop()
def delete(self):
self.progress.pack_forget()
self.progress2.pack_forget()
选项卡控件
def interface(self):
""""界面编写位置"""
notebook = tk.ttk.Notebook(self.root)
page1 = tk.Frame(notebook, background="light yellow")
tk.Label(page1, text="这是 tab1 的界面").pack()
page2 = tk.Frame(notebook, background="light pink")
tk.Label(page2, text="这是 tab2 的界面").pack()
notebook.add(page1, text="Tab1")
notebook.add(page2, text="Tab2")
notebook.pack(fill=tk.BOTH, expand="yes")
该小部件有助于可视化并允许在项目的层次结构上进行导航。它可以显示层次结构中每个项目的多个功能。它可以像在 Windows
资源管理器中一样构建类似于用户界面的树形视图 9。
它的语法格式:
tv = ttk.Treeview(root, height=20, selectmode = 'browse',show= 'tree')
delete(*tree.get_children())
| 删除节点 37
参数 | 说明 |
---|---|
父对象 | 表示这个文本框将建立在哪一个窗口内 |
columns |
列标识符的列表,用于指定列数及其名称。 |
displaycolumns |
列标识符(符号或整数索引)的列表,用于指定显示哪些数据列出及其出现的顺序,或字符串 “#all" |
height |
指定应可见的行数。注意,请求的宽度由列宽度的总和确定。 |
padding |
指定窗口小部件的内部填充。填充是最多四个长度规范的列表。 |
selectmode |
控制内置类绑定如何管理选择。extended ,browse 或 none 。如果设置为 extended (默认),则一次将仅选择一个项目。如果为 none ,则选择不会更改。 |
show |
包含零个或多个以下值的列表,指定要显示树的哪些元素。 - tree:在第0列中显示树标签。 - headings:显示标题行。 默认值为 tree headings ,即显示所有元素。注意:即使未指定 show='tree ,列 #0 始终引用树列。 |
def interface(self):
""""界面编写位置"""
self.tree = tk.ttk.Treeview(self.root, show='tree')
# 监听self.tree中item被选中的事件
self.tree.bind("<>" , self.item_select)
# 第一个参数为父节点, 第二个为此项在父节点中的位置(父节点为空时,默认为根节点)
item1 = self.tree.insert("", 0, text="广东省")
# 在第一个节点中插入如下子节点
self.tree.insert(item1, 0, text="广州市")
self.tree.insert(item1, 1, text="深圳市")
item2 = self.tree.insert("", 1, text="湖北省")
self.tree.insert(item2, 0, text="武汉市")
self.tree.insert(item2, 1, text="宜宾市")
self.tree.pack()
def item_select(self, event):
for select in self.tree.selection():
print(self.tree.item(select, "text"))
def interface(self):
""""界面编写位置"""
# show用于禁止列顶部标签。columns用于设置每一列的列标识字符串
self.tree = ttk.Treeview(self.root, show='headings', columns=['0', '1', '2'])
# 监听tree中item被选中的事件
self.tree.bind("<>" , self.item_select)
# 设置表头名称
self.tree.heading(0, text='序号', command=lambda: self.head_onclick('序号'))
self.tree.heading(1, text='姓名', command=lambda: self.head_onclick('姓名'))
self.tree.heading(2, text='年龄', command=lambda: self.head_onclick('年龄'))
# 设置每列中元素的样式
self.tree.column(0, anchor='center')
self.tree.column(1, anchor='center')
self.tree.column(2, anchor='center')
# "end" 表示往父节点的最后一个位置插入
item1 = self.tree.insert("", "end", values=("1", "赵二", "19"))
item1 = self.tree.insert("", "end", values=("2", "张三", "20"))
item1 = self.tree.insert("", "end", values=("3", "李四", "22"))
item1 = self.tree.insert("", "end", values=("4", "王五", "18"))
self.tree.place(relx=0.01, rely=0.1, width=500, height=500)
def item_select(self, event):
for select in self.tree.selection():
print(self.tree.item(select, "values"))
def head_onclick(self, type):
print(type)
参考这里 38‘ 39
滚动条部件中包含滑块 slider
, 前后两个箭头 arrow1
, arrow2
, 滑块槽 trough
(分前后两头滑块槽 trough1
/ trough2
),滑块的大小及位置代表可见的部份占全部内容的比例及位置 (0.0 ~ 1.0)
。
Scrollbar
(滚动条) 允许查看另一个小部件的所有部分,其内容通常大于可用空间。
Tkinter
Scrollbar
小部件不属于任何其他小部件,例如 Text
和 Listbox
。
相反,Scrollbar
是一个独立的小部件。
Tkinter
Scrollbar
小部件基本上提供了滑动控制器,用于实现垂直滚动小部件,如 Listbox
、Canvas
和 Text
。
使用 Scrollbar
小部件,还可以尝试在条目小部件上创建水平滚动条。
当滚动条设置为垂直时,Scrollbar
用于滚动内容以垂直查看整个内容。 水平滚动条用于水平滚动内容。
Scrollbar()
语法将用于获取具有以下属性的滚动条 master
和 option
/ options
。
创建 Scrollbar
的语法如下:
w = scrollbar(master, option/options, ...)
参数说明如下:
参数 | 说明 |
---|---|
Master |
Tkinter 滚动条的这个 master 属性只代表父窗口。 |
option / options |
Scrollbar 的选项 / 选项属性将具有滚动条小部件常用的选项列表。这些选项 / 选项主要用作键值对,以逗号分隔。 |
常用选项列表:
参数 | 说明 |
---|---|
activebackground |
当鼠标/光标点在滚动条 / 滑块上时,Scrollbar 的 activebackground 选项用于为滑块 / 滚动条 / 箭头 / 箭头 / 光标符号着色。 |
activerelief |
active 时的滑块花边样式,内定为 RAISED |
Bg |
当鼠标 / 光标点实际上不在滚动条 / 滑块上时,Scrollbar 的 bg 选项对于更改滚动条 / 箭头 / 光标点的背景非常有帮助。 |
bd |
用于设置围绕整个槽的周边的 3d 边框的宽度,以及滑块和鼠标点 / 箭头 / 光标点上的 3d 效果的宽度。默认情况下,槽的每个角落周围 / 旁边都没有边框。连同在滑块和箭头 / 光标点周围有 2 个像素的边框一起。 |
command |
每次滚动条 / 滑块移动时根据需要调用的过程。 |
cursor |
使光标在滚动条位于鼠标 / 光标点下方时出现。 |
elementborderwidth |
用于调整滑块和箭头/光标周围的边框宽度。默认情况下,elementborderwidth 的值为 1 。可以根据需要 / 需要使用 elementborderwidth 选项添加任何边框宽度。 |
highlightbackground |
用于在滚动条 / 滑块没有任何焦点时突出显示颜色。 |
highlightcolor |
用于当鼠标点 / 滚动条 / 滑块有焦点时高亮的焦点颜色。 |
highlightthickness |
用于设置高亮的粗细,但默认情况下,高亮粗细值设置为 1 。您可以将值设置为 0 以抑制焦点高亮的显示。 |
jump |
控制用户拖动 / 拖动滑块时发生的情况。默认情况下,跳转选项的 0 值会导致每个小滑块拖动的回调命令。如果跳转选项值设置为值 1 ,则如果用户没有释放鼠标 / 光标按钮,则不会调用回调。 |
orient |
用于将方向设置为水平/垂直。就像 orient=HORIZONTAL 或 orient =VERTICAL 。 |
repeatDelay |
控制在滑块重复向特定方向移动之前,按钮 1 在槽中按下的时间。默认情况下,重复延迟 (repeatdelay=300) 为 300 ,单位为毫秒。 |
repeatInterval |
重复间隔,以毫秒为单位重复按下滑块槽,内定 100ms。 |
takefocus |
用于通过滚动条小部件切换焦点,但如果您不想要此功能/行为,可以将其设置为值 0。 |
troughcolor |
滑块槽的颜色。 |
width |
用于设置滚动条/滑块的宽度( x 尺寸用于垂直,y 尺寸用于水平)。默认情况下,宽度值为 16 ( width=16 )。 |
滚动条部件的方法:
方法 | 说明 |
---|---|
activate(element=None) |
返回鼠标所在零件,slider / arrow1 / arrow2 / (其他) , 或者设置聚焦在该零件 |
delta(dx, dy) |
如同鼠标移动 (dx, dy) , 返回目前滑块相对移动量,该值在 -1.0 ~ +1.0 |
fraction(x, y) |
返回相对于 (x, y) 位置的滑块位置,0.0 ~ +1.0 |
get() |
返回目前滑块位置的前缘 a 与后缘 b , (a, b) , 0.0 ~ +1.0 |
identify(x, y) |
返回 (x, y) 所在的零件,slider / arrow1 / arrow2 / trough1 / trough12 / (其他) |
set(first, last) |
要带有滚动条的主部件,其 xscrollcommnad / yscrollcommand 设为本方法,本方法的参数同 get 方法返回的结果同意义 |
滚动条部件的回调:
方法 | 说明 |
---|---|
command (tk.SCROLL, -1, tk.UINTS) |
滚动条前移一小单位 |
command (tk.SCROLL, 1, tk.UINTS) |
滚动条后移一小单位 |
command (tk.SCROLL, -1, tk.PAGES) |
滚动条前移一小页面 |
command (tk.SCROLL, 1, tk.PAGES) |
滚动条后移一小页面 |
command (tk.MOVETO, f) |
滚动条移到相对位置 f: 0.0 ~ +1.0 |
设置主部件与滚动条部件的连接:
xscrollcommand
/ yscrollcommand
为滚动条部件的 set
方法;command
为主部件的 xview
/ yview
方法;grid
方法选项 sticky
, 应该要设置为 EW
/ NS
;注:移动滚动条并不会移动滚动其主部件
首先,创建一个 Scrollbar
小部件。
其次,将 Scrollbar
与可滚动的小部件链接起来。
下面展示了如何使用 ttk.Scrollbar
构造函数创建 Scrollbar
小部件:
from tkinter import ttk
scrollbar = ttk.Scrollbar(
container, # 滚动条所在的窗口 或 Frame
orient='vertical', # 指定滚动条是需要水平滚动还是垂直滚动
command=widget.yview # 参数允许滚动条小部件与滚动小部件进行通信
)
Scrollbar
小部件还需要向 Scrollbar
反馈当前可见的整个内容区域的百分比。
每个 Scrollbar
小部件都有一个 yscrollcommand
和 / 或 xscrollcommand
选项。
可以将 scrollbar.set
方法分配给它:
widget['yscrollcommand`] = scrollbar.set
Text
小部件是几种可滚动小部件之一。
关于组件如何绑定一个水平滚动条,Text
组件有点不一样,因为它是可以自动换行的,如果自动换行,那水平滚动条绑定成功也没有什么用。
这时,wrap
参数就显得很重要了,加入 wrap=NONE
后,文本只要没有硬换行符,超过 Text
都不会换行,这时,超长看不到的文本就可以通过水平滚动条来查看了。
以分别将 wrap=WORD
和 wrap=CHAR
代替 wrap=NONE
测试一下,这2种情况都会换行,绑定水平滚动条就没有什么意义了 28。
下面的程序演示了一个简单的用户界面,它由 Text
和 Scrollbar
小部件组成 28:
def interface(self):
""""界面编写位置"""
text = tk.Text(self.root, width=50, height=5)
text.grid(row=0, column=0, sticky='ew')
text.insert('insert', '1'*1000)
scrollbar = ttk.Scrollbar(self.root, orient='vertical', command=text.yview)
scrollbar.grid(row=0, column=1, sticky='ns')
text['yscrollcommand'] = scrollbar.set
运行效果如下:
参考这里 40
def interface(self):
""""界面编写位置"""
# 创建文本框text,设置宽度、文本显示的行数,以及 wrap 类型
text = tk.Text(self.root, width=20, height=5, wrap=NONE)
text.insert(INSERT, '1' * 1000)
text.grid(row=0, column=2)
x_scrollbar = tk.Scrollbar(self.root, orient='horizontal', command=text.xview)
x_scrollbar.grid(row=1, column=2, sticky='we')
text['xscrollcommand'] = x_scrollbar.set
或者,
def interface(self):
""""界面编写位置"""
# 创建水平方向的滚动条
x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
x_scrollbar.grid(row=1, column=2, sticky=tk.E + tk.W)
# 创建文本框text,设置宽度、文本显示的行数,以及 wrap 类型
text = tk.Text(self.root, width=20, height=5, wrap=NONE, xscrollcommand=x_scrollbar.set)
text.insert(INSERT, '1' * 1000)
text.grid(row=0, column=2)
x_scrollbar['command'] = text.xview
def interface(self):
""""界面编写位置"""
# 创建文本框text,设置宽度、文本显示的行数,以及 wrap 类型
text = tk.Text(self.root, wrap=NONE)
text.insert(INSERT, '1' * 1000)
text.grid(sticky=W+E+S+N)
# scrollbar向4边扩展
# 创建水平方向的滚动条
x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
x_scrollbar.grid(row=50, columnspan=10, sticky=W + E)
# src向东西扩展
# 滚动设置相互绑定
text.config(xscrollcommand=x_scrollbar.set)
x_scrollbar.config(command=text.xview)
参考这里 39’ 41
需要同时配置 Listbox
和 Scrollbar
以使他们能正确地耦合在一起。
yscrollcommand
回调设置为 Scrollbar 的 set
。yscrollcommand
是由滚动条控制的可滚动控件的选项,用于与垂直滚动条进行通信。Scrollbar
的 command
到 Listbox
的 yview
。当用户移动 Scrollbar
的滑块时,它将使用适当的参数调用 yview
方法。def interface(self):
""""界面编写位置"""
font = ('Courier New', 16, 'bold')
elements = ('List for House', 'List for Friend', 'List for Cash', 'List for Car',
'List for Motorcycle', 'List for Boat', 'List for Airplane')
# 创建垂直方向的滚动条
y_scrollbar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
y_scrollbar.pack(side='right', fill='y')
# 创建选项框
list_box = tk.Listbox(self.root, font=font, selectmode=tk.EXTENDED,
width=20, height=3, activestyle='dotbox',
yscrollcommand=y_scrollbar.set)
list_box.insert(tk.END, *elements)
list_box.pack(side='top', fill='both')
y_scrollbar.config(command=list_box.yview)
运行效果如下:
def interface(self):
""""界面编写位置"""
font = ('Courier New', 16, 'bold')
elements = ('List for House', 'List for Friend', 'List for Cash', 'List for Car',
'List for Motorcycle', 'List for Boat', 'List for Airplane')
# 创建水平方向的滚动条
x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
x_scrollbar.grid(row=1, column=0, sticky=tk.E + tk.W)
# 创建选项框
list_box = tk.Listbox(self.root, font=font, selectmode=tk.EXTENDED,
width=15, height=5, activestyle='dotbox',
xscrollcommand=x_scrollbar.set)
list_box.insert(tk.END, *elements)
list_box.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
x_scrollbar['command'] = list_box.xview
运行效果如下:
def interface(self):
""""界面编写位置"""
font = ('Courier New', 16, 'bold')
elements = ('List for House', 'List for Friend', 'List for Cash', 'List for Car',
'List for Motorcycle', 'List for Boat', 'List for Airplane')
# 创建水平 & 垂直方向的滚动条
x_scrollbar = tk.Scrollbar(self.root, orient=tk.HORIZONTAL)
x_scrollbar.grid(row=1, column=0, sticky=tk.E + tk.W)
y_scrollbar = tk.Scrollbar(self.root, orient=tk.VERTICAL)
y_scrollbar.grid(row=0, column=1, sticky=tk.N + tk.S)
# 创建选项框
list_box = tk.Listbox(self.root, font=font, selectmode=tk.EXTENDED,
width=15, height=5, activestyle='dotbox',
xscrollcommand=x_scrollbar.set,
yscrollcommand=y_scrollbar.set)
list_box.insert(tk.END, *elements)
list_box.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
x_scrollbar['command'] = list_box.xview
y_scrollbar['command'] = list_box.yview
运行效果如下:
def interface(self):
""""界面编写位置"""
self.cb = tk.ttk.Combobox(master=self.root,
height=10,
width=20,
state='normal',
cursor='arrow',
font=('', 15),
value=('中国', '美国', '英国',
'全宇宙第一强国,谁也无法超越的超级大国,你谁呀?')
)
self.cb.pack(padx=5, pady=10)
scr2 = ttk.Scrollbar(orient=tk.HORIZONTAL)
# 水平滚动条
scr2.pack(fill=tk.X, padx=10, pady=(0, 10))
self.cb.config(xscrollcommand=scr2.set)
# combobox绑定滚动条设置
scr2.config(command=self.cb.xview)
运行效果如下,
参考这里 38’ 42
为了更方便,Tkinter
提供了 ScrolledText
小部件,它与链接到垂直滚动条的文本小部件执行相同的操作。
要使用 ScrolledText
小部件,需要从 tkinter.scrolledtext
模块导入 ScrolledText
类。从技术上讲,ScrolledText
类继承自 Text
类。ScrolledText
小部件使用插入在容器和 Text
小部件之间的 Frame
小部件来保存 Scrollbar
小部件。因此,ScrolledText
具有与 Text
小部件相同的属性和方法。 此外,包括 pack
、grid
和 place
在内的几何管理器方法仅限于 Frame
。
def interface(self):
""""界面编写位置"""
from tkinter.scrolledtext import ScrolledText
st = ScrolledText(self.root, wrap=WORD, width=10, height=5)
st.insert(INSERT, '1' * 500)
st.pack(fill=tk.X, side=tk.TOP, expand=True)
def interface(self):
""""界面编写位置"""
from tkinter import scrolledtext
# 创建文本框text,设置宽度100,high不是高度,是文本显示的行数设置为3行
e4 = tk.Text(self.root, width=20, height=5)
e4.insert(INSERT, '1' * 1000)
e4.grid(row=0, column=1, sticky=S + W + E + N)
# 创建滚动条
scroll = tk.Scrollbar(orient="vertical", command=e4.yview)
# 将滚动条填充
e4.config(yscrollcommand=scroll.set)
# 将滚动条与文本框关联
# scroll['command']=e4.yview
scroll.grid(row=0, column=2, sticky=S + W + E + N)
分类 | 简要说明 |
---|---|
messagebox |
消息对话框 |
filedialog |
文件对话框 |
colorchooser |
颜色选择对话框 |
from tkinter import *
from tkinter import messagebox
root = Tk()
root.title("主窗口") # 设置窗口标题
result = messagebox.askokcancel("标题", "这是内容", parent=root)
# parent指定依托的父窗口,若不指定,默认为根窗口
messagebox.askquestion("标题", "这是question窗口")
messagebox.askretrycancel("标题", "这是retry cancel窗口")
messagebox.showerror("标题", "这是error窗口")
messagebox.showinfo("标题", "这是info窗口")
messagebox.showwarning("标题", "这是warning窗口")
root.mainloop()
参考这里 43’ 44
参数 | 含义 |
---|---|
title |
设置文件对话框的标题 |
initialdir |
设置默认打开的路径 |
filetypes |
文件类型筛选。它的值是一个列表,列表中的元素必须是一个二元元组。元组的第一个元素是类型名称,第二个是类型后缀名。 |
from tkinter import *
from tkinter import filedialog
def onclick():
file_name = filedialog.askopenfilename(
title="Open File", initialdir="/Users/xueshanzhang/Downloads",
filetypes=[("PNG", ".png"), ("PDF", "pdf")])
print('Open ', file_name)
def save_file():
file_name = filedialog.asksaveasfilename(
title="Save File", initialdir="/Users/xueshanzhang/Downloads")
print('Save as ', file_name)
root = Tk()
Button(root, text="Browse", command=onclick).pack()
Button(root, text="Save", command=save_file).pack()
root.mainloop()
from tkinter import *
from tkinter import filedialog
root = Tk()
root.geometry('700x150+400+300')
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
def onclick():
# get a directory path by user
filepath=filedialog.askdirectory(
initialdir=r"F:\python\pythonProject",
title="Open Directory"
)
label = Label(root, text=filepath, font=('italic 14'))
label.pack(pady=20)
Button(root, text='select directory', command=onclick).pack()
root.mainloop()
from tkinter import *
from tkinter import colorchooser
def onclick():
color = colorchooser.askcolor()
# 返回值是一个元组,第一个元素是RGB色值元组,第二个是对应的16进制色值
print('color', color)
# color((173, 255, 0), '#adff00')
root = Tk()
Button(root, text="Choose Color", command=onclick).pack()
root.mainloop()
参考这里 45‘ 46
canvas
的中文意思就是 画布
。在 GUI
中,canvas
是一个非常基础的概念,基本上任何跟 GUI
相关的编程语言、库、框架等,都会有 canvas
,只要搞懂了canvas
是什么,就一通百通了。
首先,通俗地解释一下什么是 canvas
。就像画油画一样,得先准备一张画布,然后再在这张画布上进行创作,你可以在画布上画任何你想画的东西,直线、圆、椭圆等。
而在 tkinter
中,canvas
就是类似的作用。提供给你一张 “画布”,你可以在上面 “画” 任何基础图形,也可以 “画” 其他控件。
它的语法格式 Canvas(master, cnf={}, **kw)
想画画,通常要选择一个指定大小的画布,canvas
可以通过属性 width
、height
来选择 canvas
的尺寸。
参数 | 含义 |
---|---|
width |
指定 canvas 的宽度。 |
height |
指定 canvas 的高度。 |
bg |
指定 canvas 的背景颜色。 |
from tkinter import *
from tkinter.constants import RIGHT, LEFT, X, Y, BOTH
root = Tk()
root.title('Canvas')
width, height = 300, 200
root.geometry(f'{width}x{height}')
cav = Canvas(root, width=width, height=height, bg='lightblue')
cav.pack()
root.mainloop()
方法 | 作用 |
---|---|
cursor |
指定鼠标的显示样式,当鼠标落在画布区域时。样式的值是 arrow , watch , cross’ 。 |
relief |
指定边框样式,默认样式为 flat ,样式的种类有 flat , groove , raised , ridge , solid , sunken 。 |
create_line(*args, **kw) |
画直线,args 参数为 x1 , y1 , … , xn , yn 坐标值; kw 参数为其他属性; fill 用来填充直线的颜色; outline 外围轮廓的颜色; width 为线宽 |
create_oval(*args, **kw) |
画椭圆,args 参数为 x1 , y1 , x2 , y2 ;坐标 (x1,y1) , (x2,y2) 指定一个矩形 (正方形) 的左上角和右下角。圆或椭圆就在这个矩形内部。kw 参数为其他属性,如 fill , outline , width 。 |
create_rectangle(*args, **kw) |
画矩形,args 参数为 x1 , y1 , x2 , y2 ; 坐标 (x1,y1) ,(x2,y2) 指定一个矩形 (正方形) 的左上角和右下角。kw 参数为其他属性,如fill , outline , width 。 |
create_polygon( *args, **kw) |
画多边形,args 参数为 x1 , y1 , … , xn , yn 坐标值。kw 参数为其他属性,fill 用来设置直线的颜色; |
create_arc(*args, **kw) |
画弧线,args 参数为 x1 , y1 , x2 , y2 坐标值 kw 参数为其他属性, start 表示起始弧度,extent 表示结束弧度。根据初中的几何知识,圆弧是由射线绕它的端点旋转,在旋转过程中射线上的点会形成一条狐。 |
create_text(*args, **kw) |
显示文字, args 参数为 x1 , y1 , x2 , y2 坐标值。kw 参数为其他属性,如 fill , outline , width , font |
create_image(*args, **kw) |
显示图片 |
move |
让图形动起来 |
scale |
缩放item,语法为 scale(self,xoffset,yoffset,xscale,yscale) ,其计算公式为 (coords - offset)*scale + offset |
tag_bind |
使用 tag_bind 来绑定 item 与事件,绑定 item 与事件,只有点击到矩形的边框时才会触发事件。 |
参考这里 45
命令绑定的缺陷是,只有 Button
和一小部分控件支持。
功能单一。命令只能绑定到鼠标左键单击和空格键点击事件,无法实现焦点、鼠标滚轮、快捷键响应等等丰富的交互情况。
在不需要给出参数的事件中,
简单举例如下,
import tkinter as tk
def callback():
print("被点击了")
root = tk.Tk()
tk.Button(root, text='Click', command=callback).pack()
root.mainloop()
而在需要给出参数的事件中,举例如下:
lambda
表达式;import tkinter as tk
def callback(args):
print("被点击了", args)
root = tk.Tk()
tk.Button(root, text='单击', command=lambda: callback("按钮")).pack()
root.mainloop()
command
;import tkinter as tk
class Command:
def __init__(self, func, *args):
self.func = func
self.args = args
def __call__(self):
self.func(*self.args)
def callback(args):
print("被点击了", args)
root = tk.Tk()
tk.Button(root, text='单击', command=Command(callback, "按钮")).pack()
root.mainloop()
所谓事件,就是在用户按下一个键或点击鼠标时,应用程序需要做出的反应。简单说就是对外部刺激做出的反应。
当窗口小控件中注册的事件发生时,会回调关联的处理函数,并将事件对象的实例作为参数传递到这个处理函数中 47。
类型 | 名称 | 描述 |
---|---|---|
36 | Activate |
The state option of a widget changes from inactive to active. |
4 | Button |
One mouse button is pressed |
5 | ButtonRelease |
One mouse button is released |
22 | Configure |
The size of the widget is changed |
37 | Deactivate |
The state option of a widget change from active to inactive. |
17 | Destroy |
A widget is being destroyed. |
7 | Enter |
The mouse pointer is moved into a visible part of a widget. |
12 | Expose |
Some part of the widget or application is visible after having been covered up by another window. |
9 | FocusIn |
The input focus was moved into a widget. |
10 | FocusOut |
The input focus was moved out of a widget. |
2 | KeyPress |
A key is pressed. |
3 | KeyRelease |
A key is released. |
8 | Leave |
The mouse pointer is moved out of a widget. |
19 | Map |
A widget is being placed on a container e.g., calling the pack() or grid() method. |
6 | Motion |
The mouse pointer is moved entirely within a widget. |
38 | MouseWheel |
The user moved the mouse wheel up or down. |
18 | Unmap |
A widget is being unmapped and is no longer visible, for example when calling the grid_remove() method on the widget. |
15 | Visibility |
At least some part of the application window becomes visible on the screen. |
常用的几个鼠标事件,
事件 | 含义 |
---|---|
|
鼠标左击事件 |
|
鼠标滚轮点击 |
|
鼠标右击事件 |
|
鼠标左双击事件 |
|
鼠标左三击事件 |
关于事件回调传参 之前的命令回调我们都是通过 lambda
表达式传参,这里的事件回调也一样,只是稍微有一点区别:
def callback(event, a, b):
# 修改回调函数,添加a、b两个参数
print(a, b)
print("EventType=", event.type)
frame.bind("" , lambda event: callback(event, 1, 2))
# 注册回调时,在lambda表示中需要定义event参数
import tkinter as tk
root = tk.Tk()
tk.Label(root, text='按键').pack()
def callback(event):
print("EventType=", event.type)
print("keysym=", event.keysym)
frame = tk.Frame(root, bg='khaki', width=100, height=80)
frame.pack()
root.bind("" , callback) # a 键
root.bind("" , callback) # F1 键
root.bind("" , callback) # Ctrl + Alt + a 键
root.mainloop()
有时候我们需要用代码模拟生成一个事件,发送给监听者,而不是通过操作事件源产生事件。
tkinter
中所有的 widget
都包含一个公共方法 event_generate
, 这个方法就是用来产生相应的事件的。
event_generate("<>" )
要想查看这些内置的事件,需要查看 Tk
/ tcl
的文档,tkinter
只是对 Tk
/ tcl
的封装,因此 tkinter
的文档并不是非常全面。
属性 | 含义 |
---|---|
char |
键盘事件,按键的字符 |
delta |
鼠标滚动事件,鼠标滚动的距离 |
height 、width |
仅用于 Configure 事件,即当控件形状发生变化之后的宽度和高度.相当于SizeChanged 事件 |
keycode |
键盘事件,按键码 |
keysym 、keysym_num |
按键事件 |
num |
鼠标事件,鼠标按键码,1 为左键,2 为中建,3 为右键 |
serial |
相当于 Event 的 ID |
state |
用来表示修饰键的状态,即 ctrl , shift , alt 等修饰键的状态 |
time |
事件发生的时间 |
type |
事件的类型 |
widget |
事件源控件 |
x 、y ,x_root 、y_root |
鼠标事件中鼠标的位置。x_root 、y_root 为绝对坐标,x ,y 为相对坐标。 |
事件有三种绑定级别,实际开发中选择合适的一种即可:
鼠标事件
绑定到 Frame
实例上。frame.bind("" , callback)
Entry
控件都将绑定到事件,该事件将调用名为 paste
的函数,类级绑定须慎用,以免造成不可预知的问题。my_entry.bind_class('Entry','' ,paste)
root.bind_all('' ,show_help)
只要应用程序处于焦点,按 F1
键将始终触发 show_help
函数回调。
事件被注册后,是可以取消的,三种级别绑定的取消方法如下:
entry.unbind('')
root.unbind_all('')
root.unbind_class('Entry', '')
几乎所有的GUI程序中,都天生的适合运用面向对象思维开发。在GUI程序中使用面向过程的范式,则存在一些缺陷,这也是为什么C语言不适合开发大型GUI程序的原因:
OOP (Object Oriented Programming 面向对象程序设计)
实际上是一种代码组织方式,它将焦点转移到我们想要操作的对象上,而不是操纵它们所需的逻辑。这与面向过程编程形成对比,面向过程编程将程序视为一个逻辑过程,它接受输入,处理并产生一些输出。
OOP
提供了一些好处,例如数据抽象,封装,继承和多态。此外,OOP
为程序提供了清晰的模块化结构。代码修改和维护很容易,因为可以在不修改现有对象的情况下创建新对象。
通常在 Python
中写 Tkinter
界面程序时,很多人会使用这种聚合式的写法,实际上这并不是真正纯粹的面向对象的 GUI
写法,但 tkinter
本身也仅仅是对过程式的 tcl
库的封装,继承小控件并不能真正去重写控件的表现行为,因此是否继承也显得无关紧要,但是在类似 Qt
这种库中则不然。
下面提供一个编码示例:
import tkinter as tk
class App:
def __init__(self, root):
self.root = root
self.set_window()
self.create_top()
self.create_body()
self.create_bottom()
# 设置窗口
def set_window(self):
self.root.title("测试")
self.root.resizable(False, False)
# 创建顶部
def create_top(self):
tk.Label(self.root, text="Top").pack()
# 创建主体
def create_body(self):
self.input = tk.StringVar()
tk.Entry(self.root, textvariable=self.input).pack()
# 创建底部
def create_bottom(self):
tk.Button(self.root, text="Bottom", command=self.onclick).pack()
# 按钮回调函数
def onclick(self):
print(self.input.get())
if __name__ == "__main__":
root = tk.Tk()
App(root)
root.mainloop()
通过继承不能改变控件的表现行为,但是继承式的写法,仍然会让代码更简洁,逻辑更清晰,在其他的面向对象的 GUI
库中,这是一种常用的写法。
下面是示例:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.set_window()
self.create_top()
self.create_body()
self.create_bottom()
# 设置窗口
def set_window(self):
self.title("测试")
self.resizable(False, False)
# 创建顶部
def create_top(self):
tk.Label(self, text="Top").pack()
# 创建主体
def create_body(self):
self.input = tk.StringVar()
tk.Entry(self, textvariable=self.input).pack()
# 创建底部
def create_bottom(self):
tk.Button(self, text="Bottom", command=self.onclick).pack()
# 按钮回调函数
def onclick(self):
print(self.input.get())
if __name__ == "__main__":
app = App()
app.mainloop()
%todo:
python之Tkinter使用详解 ↩︎
TkDocs ↩︎
Tkinter从入门到实战详解 ↩︎ ↩︎ ↩︎ ↩︎
Tkinter列表框和组合框控件详解 ↩︎
Python | GUI | Tkinter - 1. 基本控件 ↩︎
Python | GUI | Tkinter - 2. 组件使用 ↩︎
Python | GUI | Tkinter - 3. 多窗体 ↩︎
Python | GUI | Tkinter - 4. 多线程的暂停和继续以及文件间调用 ↩︎
Python GUI应用程序中的分层树视图(代码示例) ↩︎ ↩︎
Tcl Developer Xchange ↩︎
Tcl/Tk Insight ↩︎
Tcl 编程/简介 ↩︎
Tcl Files ↩︎
为什么很多Python开发者写GUI不用Tkinter,而要选择PyQt和wxPython或其他? ↩︎
3.1 高级控件学习 ↩︎
Python3 Tkinter 实例教学 (六)标签Label 颜色设置 ↩︎
《tkinter实用教程五》tkinter ttk.Frame控件 ↩︎
Tkinter 组件详解(十四):Menubutton ↩︎
Tkinter菜单Menu的使用示例 ↩︎
Python tkinter Listbox 用法與範例 ↩︎
Tkinter列表框和组合框控件详解 ↩︎ ↩︎
How to assign a command or callback to a tkinter listbox [duplicate] ↩︎
Tkinter python(图形开发界面) ↩︎
Python tkinter Listbox 用法與範例 ↩︎
Tkinter 学习笔记:如何用get()方法获取 Text() 和 Entry()文本框的内容 ↩︎ ↩︎
如何設定 Tkinter 文字輸入控制元件的高度和寬度 ↩︎
Python之tkinter 文本框Entry的基本应用 ↩︎
强大的tkinter的多行文本框组件Text ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Python之tkinter 组合框 Combobox ↩︎
Python GUI开发之Tkinter基础篇14:Combobox组件 ↩︎ ↩︎ ↩︎
tkinter.ttk组件combobox讲解 ↩︎
Python tkinter – 第12章 Scale属性 ↩︎
Python Tkinter PanedWindow 控件 ↩︎
python-如何使Tkinter窗口跳到最前面? ↩︎
python tkinter窗口弹出置顶的方法 ↩︎
How i can hide a Progressbar()? ↩︎
【python】如何使用Tkinter清除整個Treeview ↩︎
Python编程实例-Tkinter GUI编程-Scrollbar与ScrolledText ↩︎ ↩︎
Tkinter (17) 滚动条部件 Scrollbar ↩︎ ↩︎
The horizontal scrollbar didn’t work in Tkinter ↩︎
Tkinter 教程-滚动条 ↩︎
tkinter文本实时更新滚动显示和scrollbar 与grid滚动条能拖拽使用 ↩︎
tkinter filedialog ↩︎
Tkinter askdirectory() Method ↩︎
tkinter-canvas详解 ↩︎ ↩︎
Tkinter Canvas画布控件详解 ↩︎
Tkinter Event Binding ↩︎