The most complete tutorial of Python tkinter (GUI programming) module (below)

Previous: Python tkinter (GUI programming) module full solution (in)_Python zzy's blog-CSDN blog

2 tkinter main module

2.24 Canvas

Canvas is a canvas component on which users can draw graphics, images, text, components, and move the drawn objects on it.

Reference materials: Python --- (11) Tkinter window component: Canvas_Myopia's down-to-earth blog-CSDN blog

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

parameter effect
highlightthickness Set the width of the highlighted border; most components have this parameter. What needs to be emphasized here is that Canvas has highlightthickness, which makes the border change color sometimes and affects the effect, so it is best to set it to 0
scrollregion Set the scrolling range of the Canvas. The format is (x1, y1, x2, y2), which represents a rectangle formed by the coordinates of the upper left corner and the coordinates of the lower right corner. If not specified, the scroll bar cannot be used normally
confine Whether to allow scrolling beyond the range specified by scrollregion, the default is True
xscrollcommand scroll in x direction
yscrollcommand scrolling in the y direction
xscrollincrement The scrolling step in the x direction, such as "2c" means 2 centimeters, the optional units are "c" (centimeter), "i" (inch), "m" (millimeter), "p" (DPI)
yscrollincrement The scrolling step in the y direction, the format is the same as xscrollincrement

Common methods:

method effect
addtag_above(newtag, tagOrId) Add a tag to the canvas object above tagOrld
addtag_all(newtag) Add tags to all objects in the canvas
addtag_below(newtag, tagOrId) Add a tag to the canvas object below tagOrld
addtag_closest(newtag, x, y, halo=None, start=None) With (x, y) as the center, add a tag to the canvas object whose distance is within halo; if start (a canvas object) is specified, then this method will add a tag to the canvas object below but closest to the object
addtag_enclosed(newtag, x1, y1, x2, y2) Add a tag to the canvas object within the (x1, y1, x2, y2) rectangle (the canvas object must be completely within the rectangle)
addtag_overlapped(newtag, x1, y1, x2, y2) Add a tag to the canvas object within the (x1, y1, x2, y2) rectangle (the canvas object does not have to be completely within the rectangle, and part of it is also within the rectangle)
addtag_withtag(self, newtag, tagOrId) Add a tag to the canvas object. If the canvas object already has a tag, then add a new tag to all canvas objects that have the tag; if the canvas object does not have a tag, then add a tag to this object
bbox(*args) Returns a four-tuple (x1, y1, x2, y2) used to describe the rectangular range of the canvas object specified by args
canvasx(screenx, gridspacing=None) Convert window x-coordinates to canvas x-coordinates
canvasy(screeny, gridspacing=None) Convert window y coordinates to canvas y coordinates
coords(*args) If only the canvas object is provided as a parameter, the position of the canvas object is returned (x1, y1, x2, y2); if coords(tagOrId, x1, y1, x2, y2) is provided, the position of the tagOrId canvas object is moved to (x1 , y1, x2, y2)
create_arc(*args, **kw) Draw an arc, bow or fan, and return the id of the canvas object
create_bitmap(*args, **kw) Draw a bitmap and return the id of the canvas object
create_image(*args, **kw) Draw a picture and return the id of the canvas object (the name of the picture object)
create_line(*args, **kw) Draw one or more line segments and return the id of the canvas object
create_oval(*args, **kw) Draw an ellipse and return the id of the canvas object
create_polygon(*args, **kw) Draw a polygon and return the id of the canvas object
create_rectangle(*args, **kw) Draw a rectangle and return the id of the canvas object
create_text(*args, **kw) Draw text and return the id of the canvas object
create_window(*args, **kw) Draw the component and return the id of the canvas object (the name of the component object)
delete(*args) delete canvas object
dtag(*args) You need to specify the canvas object and the tag to be deleted. If you do not specify the tag to be deleted, all tags will be removed from the canvas object
find_above(tagOrId) Returns the canvas object id above tagOrId
find_all() Returns a tuple of ids for all objects on the canvas
find_below(tagOrId) Returns the canvas object id under tagOrId
find_closest(x, y, halo=None, start=None) Returns a tuple of canvas objects close to (x, y)
find_enclosed(x1, y1, x2, y2) Returns a canvas object completely within (x1, y1, x2, y2)
find_overlapping(x1, y1, x2, y2) Returns the canvas object that is in contact with the position (x1, y1, x2, y2)
find_withtag(tagOrId) Returns the canvas object id specified by tagOrId
focus(tagOrId) Shift canvas focus to tagOrId
gettags(tagOrId) Returns all tags of the tagOrId canvas object
itemcget(tagOrId, option) Returns the value of the option option of the tagOrId canvas object
itemconfig(tagOrId, cnf={}, **kw) Set the option value of tagOrId
move(tagOrId, x, y) 将tagOrId在x方向上移动x个像素,在y方向上移动y个像素
postscript(cnf={}, **kw) 将画布内容封装成PostScript
scale(tagOrId, xOrigin, yOrigin, xScale, yScale) 对tagOrId对象进行缩放,xOrigin和yOrigin指定缩放位置,xScale和yScale指定缩放比例
tag_bind(tagOrId, sequence=None, func=None, add=None) tagOrId绑定事件
tag_unbind(self, tagOrId, sequence, funcid=None) tagOrId解除事件绑定
tag_lower(*args) 将一个或多个画布对象置于底部
tag_raise(*args) 将一个或多个画布对象置顶
type(tagOrId) 返回tagOrId的绘制类型,有“arc”, “bitmap”, “image”, “line”, “oval”, “polygon”, “rectangle”, “text”, 或 “window”

create_arc方法

create_arc方法用来绘制扇形,弓形或弧形。首先需传递四个参数代表(x1, y1, x2, y2)。下面是**kw选项。

参数 作用
dash 指定绘制虚线轮廓,是偶数个项目的元组,代表虚线每段长度和间隔;如(2, 5)表示虚线每段长度为2,每段间隔为5;如(2, 5, 4, 5)表示虚线为每段长度为2,每段间隔为5,每段长度为4,每段间隔为5的循环绘制
dashoffset 设置虚线开始绘制的偏移
extent 形状的角度(默认为90)
fill 填充的颜色,默认为空字符串表示无填充
stipple 使用位图作为填充,默认为空字符串表示无填充
outline 轮廓的颜色
outlinestipple 设置一种位图填充轮廓,需设定outline
start 起始位置的偏移
width 轮廓的宽度
style 绘制的样式,可以是"pieslice"(扇形,默认), "chord"(弓形), "arc"(弧形)
state 画布对象状态,可以是"normal", "disabled", "hidden"(隐藏)
tags 画布对象标签
from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_arc(0, 10, 100, 100, style="pieslice")
cv.create_arc(100, 10, 200, 100, style="chord")
cv.create_arc(200, 10, 300, 100, style="arc")

mainloop()

运行效果:

 

create_bitmap方法

create_bitmap用于绘制一个位图。首先需传递绘制的位置x, y。

参数 作用
bitmap 指定位图的名称
background 位图的背景色
foreground 位图的前景色
state 画布对象状态
tags 画布对象标签
from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_bitmap(100, 100, bitmap="info", foreground="red", background="yellow")

mainloop()

create_image方法

create_image方法用于绘制图片。首先需指定图片的位置x, y。

参数 作用
image 指定显示的图片
state 画布对象状态
tags 画布对象标签
from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

image = PhotoImage(file="monster.png")
cv.create_image(100, 100, image=image)

mainloop()

create_line方法

create_line方法用于绘制线条。需先给定一系列参数表示一系列点的位置,如0, 0, 100, 200, 200, 100,那么将会用线条把(0, 0), (100, 200), (200, 100)这几个位置按顺序连接起来(但首末项,也就是(200, 100)和(0,0)不会相连)。

参数 作用
arrow 使绘制的线条加上箭头,可以是"first"(首段加上箭头), "last"(末段加上箭头), "both"(两边都加上箭头)
arrowshape 箭头的形状,需传递一个三项元组表示箭头的三边的长度
dash 轮廓虚线
dashoffset 虚线偏移
fill 线段填充颜色
width 线段的宽
smooth 是否绘制贝塞尔曲线替代线段
splinesteps 设置多少条折线构成贝塞尔曲线,需设定smooth=True,默认为12
stipple 设置位图填充
capstyle 设置绘制的线条首端和末端的样式,可以是"butt", "projecting", "round"
joinstyle 设置相邻线段相接位置的样式,可以是"round", "bevel", "miter"
state 设置状态
tags 设置标签
from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_line(10, 10, 100, 10, 10, 70, width=10)

mainloop()

capstyle和joinstyle分别设置图形端点处和连接处的样式,效果如下所示(左边端点由capstyle设置,右边连接处由joinstyle设置)。

capstyle 效果 joinstyle
butt round
projecting bevel
round miter

create_oval方法

create_oval方法用于绘制椭圆,这个方法的参数和create_arc一致。

from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_oval(10, 10, 100, 100)

mainloop()

 

create_polygon方法

create_polygon用于绘制多边形,参数和create_line基本一样,但是没有capstyle参数,且多了outline等参数。需给定一系列坐标,会将它们连接起来,形成一个图形。

from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_polygon(0, 0, 100, 100, 200, 300)

mainloop()

 

create_rectangle方法

create_rectangle方法用于绘制矩形。参数与create_oval一致。需传递x1, y1, x2, y2表示位置。

from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_rectangle(0, 0, 100, 100)

mainloop()

create_text方法

create_text方法用于绘制文本。需提供绘制的位置x, y。

参数 作用
text 绘制的文本内容
font 文本的字体
fill 文本的颜色
anchor 文本的锚点(x, y设置的位置),可以是八个方位或"center",”默认是"center"
justify 多行文本的对齐方式,可以是"left", "center", "right"
width 文本自动换行的宽度
stipple 指定位图进行填充
state 设置状态
tags 设置标签
from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

cv.create_text(0, 0, text="Hello Canvas", font=("Arial", 14), anchor="nw")

mainloop()

 

create_window方法

create_window方法用于绘制组件,需提供绘制的位置x, y。

参数 作用
window 组件对象
width 组件的宽度
height 组件的高度
anchor 锚点
state 设置状态
tags 设置标签
from tkinter import *

root = Tk()
cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

b = Button(cv, text="BUTTON")
cv.create_window(0, 0, window=b, anchor="nw")

mainloop()

 

表示画布对象

画布对象有一系列的表示方式,可以是id或tag,它们可以传递到canvas的方法中。

当绘制一个画布对象,如create_text时,会返回一个值,就是画布对象的id。通过addtag可以添加tag,tag也可以用来表示一个画布对象。

有两个预定义的tag,分别是"all"和"current"。all表示所有的画布对象,current表示鼠标下的画布对象。如:删除画布的全部内容可写作:cv.delete("all")

postscript方法

postscript方法可以将画布内容保存下来,输出为*.ps图片文件。可设的关键字参数有:

参数 作用
colormode 设置输出图片的颜色类型,可以是"color"(彩色), "gray"(灰度), "mono"(黑白)
file 设置一个文件,将输出写入到此文件中;如果不指定此参数,将会返回输出结果的字符串
x 开始打印画布内容的左侧位置
y 开始打印画布内容的顶端位置
width 需打印画布内容的宽
height 需打印画布内容的高
rotate 如果设置为True,画面横向显示,否则纵向显示

实例:接球游戏

下面是一个简单的小游戏,用户通过按键操纵球拍,接住掉落的球。球的移动需要使用Canvas来完成。为了方便理解代码,完整代码中添加了详细注释。

from tkinter import *
import random

class Ball: #定义球类
    def __init__(self, racket):
        self.racket = racket
        
        self.id = cv.create_oval(0, 0, 20, 20, fill="yellow") #绘制一个黄色的圆形作为球
        cv.move(self.id, WIDTH//2, HEIGHT//2) #使球初始位于窗口中央
        
        self.xspeed = random.choice([3, -3]) #设置球的x速度
        self.yspeed = -3 #设置球的y速度

    def run(self):
        cv.move(self.id, self.xspeed, self.yspeed) #将球移动self.xspeed, self.yspeed个像素
        
        pos = cv.coords(self.id) #获取球的位置,返回(x1, y1, x2, y2)
        
        if pos[0] <= 0: #如果球的位置越过屏幕左侧
            self.xspeed = 3 #根据坐标系,速度设置为正则向右移动
        elif pos[2] >= WIDTH: #如果球的位置越过屏幕右侧
            self.xspeed = -3 #向右移动

        if pos[1] <= 0: #如果球的位置越过屏幕上方
            self.yspeed = 3 #向下移动
        elif pos[3] >= HEIGHT: #如果球的位置越过屏幕下方
            print("你失败了!")
            root.destroy() #接球失败,游戏结束

        if self.id in cv.find_overlapping(*cv.coords(self.racket)): #如果球碰撞到球拍
            self.yspeed = -3 #球向上弹起

class Racket: #定义球拍类
    def __init__(self):        
        self.id = cv.create_rectangle(0, 0, 90, 15, fill="blue") #绘制一个蓝色的矩形作为球拍
        cv.move(self.id, WIDTH//2, 200) #设置球拍的初始位置

        self.xspeed = 0 #球拍默认不移动
        root.bind("<Left>", self.move_left) #按左键执行self.move_left
        root.bind("<Right>", self.move_right) #按右键执行self.move_right

    def run(self):
        pos = cv.coords(self.id) #获取球拍位置
        
        if (pos[0] <= 0 and self.xspeed < 0) or \
           (pos[2] >= WIDTH and self.xspeed > 0): #如果移动方式会导致球拍超出屏幕范围
            self.xspeed = 0
        else:
            cv.move(self.id, self.xspeed, 0) #移动球拍
        
    def move_left(self, event): #左移
        self.xspeed = -3

    def move_right(self, event): #右移
        self.xspeed = 3


root = Tk()
root.focus_force() #使窗口获取焦点

cv = Canvas(root, bg="white", highlightthickness=0)
cv.pack()

root.update()
WIDTH = root.winfo_width()
HEIGHT = root.winfo_height() #获取窗口宽高

racket = Racket()
ball = Ball(racket.id)

def run():
    racket.run()
    ball.run()
    root.after(20, run)

root.after(20, run) #20毫秒后执行run
root.mainloop()

3 tkinter子模块

上面讲述的组件,只需要导入tkinter就能使用。tkinter还提供了一些子模块,你需要导入它们来使用它们提供的一些拓展的功能。

3.1 tkinter.constants

这个模块中存储了一些常用变量,在给组件指定一些参数的时候会用到。比如设置组件的relief参数,可以设为"flat", "groove"等。constants里面就有两个变量FLAT="flat", GROOVE = "groove"。这些字符串全部大写作为变量名。因此如果导入了这个模块的全部内容,Scale(root, orient="vertical")也可写作Scale(root, orient=VERTICAL)

这样做可能是为了方便拼写检查,减少错误。有些编辑器对于不存在的变量会进行突出显示,如果拼写出错了会一目了然看出来。而使用字符串的话就不便看出错误的地方。

tkinter主模块中导入了constants模块的所有内容,这意味着你不需要导入这个模块也能在主模块中使用它们。调用了from tkinter import *即可直接使用里面的常量。

3.2 tkinter.messagebox

messagebox模块提供了一些函数,用于弹出消息框。

Python3和Python2的messagebox模块略有不同。Python2的导入方式为:

from Tkinter import tkMessageBox

Python3的导入方式为:

from tkinter import messagebox

下面介绍一下messagebox模块的函数。这些函数需要提供以下参数:

参数 作用
title 消息框的标题
message 消息框的提示内容
icon 消息框显示的提示图标,可以是"error", "info", question", "warning"
parent 设置对话框的父窗口,父窗口在没有关闭对话框的情况下会一直处于阻塞禁用的状态;默认是主Tk窗口,如果启动对话框时未创建Tk,则会自动创建一个Tk
type 设置消息框下方的按钮,可以是"ok"(确定按钮), "okcancel"(确定、取消按钮), "retrycancel"(重试、取消按钮), "yesno"(是、否按钮), "yesnocancel"(是、否、取消按钮),  "abortretryignore"(中止、重试、忽略按钮)
default 默认激活哪一个按钮,可以是"abort"(中止), "retry"(重试), "ignore"(忽略), "ok"(确定),"cancel"(取消), "yes"(是), "no"(否)

下面是各函数的运行效果,以及点击按钮分别的返回值:

方法 效果 返回值
showinfo "ok"
showwarning "ok"
showerror "ok"
askquestion "yes"或"no"
askokcancel True或False
askyesno True或False
askyesnocancel True或False或None
askretrycancel True或False

注:messagebox有一个_show函数,这几个参数都是根据_show方法进行处理的。_show方法显示一个messagebox,但是返回值是按钮的名称(按钮名称参见default参数)。上面的这些方法中的一部分对_show方法返回的按钮名称进行了处理,比如askokcancel,返回的是True或False而非"ok"或"cancel"。

弹出消息框的时候,窗口会一直阻塞等待,直到给出按钮选择。如果你不清楚这是怎么做到的,可以去参考上方组件基类的wait_variable方法讲解。

实例:询问是否继续

from tkinter import *
from tkinter import messagebox

root = Tk()
root.title("游戏界面")

res = messagebox.askyesno("提示", "你输了,是否继续?")
'''
也可写作messagebox.askyesno(title="提示", message="你输了,是否继续?")
但是title/message是函数中最前面的两个参数,这么写简单一些
'''
if res:
    print("继续游戏")
else:
    print("退出")

3.3 tkinter.filedialog 

filedialog模块中提供了一些询问文件的对话框,比如弹出一个对话框,让你选择一个文件。

下面介绍filedialog的函数。这些函数中,如果用户没有选择任何文件,那么会返回空字符串。 这些函数都可以提供如下关键字参数。

参数 作用
defaultextension 默认后缀名;如果用户未指定文件名后缀,则默认使用此后缀名
filetypes 设置可选的文件类型;是多个元组组成的序列,每个元组需提供两个项,一个是文件的描述,一个是文件的后缀,如"*.txt",如果不限文件后缀名,可以写作"*.*";关于文件后缀名的写法比较自由,指定txt文件可以写作"*.txt",也可以写作".txt", "txt"
initialdir 文件选择对话框弹出时,默认位于哪一个文件夹
initialfile 文件选择框弹出时,默认选中哪一个文件
parent 设置对话框的父窗口,父窗口在没有关闭对话框的情况下会一直处于阻塞禁用的状态;默认是主Tk窗口,如果启动对话框时未创建Tk,则会自动创建一个Tk
title 对话框的标题
multiple 是否允许多选,默认为False

下面是函数的介绍:

方法 作用
askopenfilename(**options) 返回用户选择打开的文件名称(文件必须存在才能被选择)
askopenfilenames(**options) 和上面一个函数类似,不同的是此函数设置了multiple=1,允许多选
asksaveasfilename(**options): 返回用户选择另存为的文件名称(文件可以不存在,但用户需指定文件名)
askopenfile(mode="r", **options): 用户选择打开文件名称后,返回使用open函数打开的文件对象
askopenfiles(mode="r", **options): 和上面一个函数类似,不同的是此函数设置了multiple=1,允许多选
asksaveasfile(mode="w", **options) 用户选择另存为的文件名称后,返回使用open函数打开的文件对象
askdirectory(**options) 返回用户选择的文件目录;这个函数只支持上述关键字参数里面的initialdir, parent, title,此外还支持mustexist参数,表示是否用户只能选择现已存在的文件夹

实例:文本查看器

from tkinter import *
from tkinter.filedialog import askopenfilename

def load():
    filename = askopenfilename(filetypes=[("文本文档", "*.txt")])
    
    if filename:
        root.title(filename)
        
        text.config(state="normal") #先设置为normal,不然不能进行更改
        text.delete("1.0", "end")
        text.insert("1.0", open(filename, encoding="utf-8").read())
        text.config(state="disabled")
        
root = Tk()
root.title("Text Viewer")

menu = Menu(root)
root.config(menu=menu)
menu.add_command(label="Load", command=load)

text = Text(root, state="disabled")
text.pack()

root.mainloop()

3.4 tkinter.colorchooser

tkinter的子模块colorchooser,用于弹出一个对话框,让用户选择一种颜色。这个模块使用方式非常简单,有一个函数askcolor,执行后即可弹出一个颜色对话框。

用户选择完颜色后,askcolor返回选取的结果,是一个元组,第一项是选取颜色的RGB元组,第二项是选取颜色的十六进制形式"#......"。如果用户点击了取消,会返回一个两项都是空的元组(None, None)。

from tkinter import *
from tkinter import colorchooser

def choose_color():
    color = colorchooser.askcolor()
    print(color)
        
root = Tk()
Button(root, text="Choose Color", command=choose_color).pack()

mainloop()

这个方法还可以提供如下关键字参数:

参数 作用
initialcolor 颜色对话框弹出时,默认显示的颜色
parent 颜色对话框的父窗口
title 颜色对话框的标题

3.5 tkinter.ttk

参考资料:tkinter.ttk --- Tk 风格的控件 — Python 3.10.6 文档

ttk是tkinter的拓展组件库,提供了一些拓展的组件:Combobox,Notebook,Progressbar,Separator,Treeview,Sizegrip。还有一些组件主模块中已经包含了,它们的样子和原来不相同,显得更加美观,它们是Button, Checkbutton, Entry, Frame, Label, LabelFrame, Menubutton, PanedWindow, Radiobutton, Scale, Scrollbar和Spinbox(还继承ttk.Entry)。这些组件都继承ttk.Widget类。

ttk在python2中的导入方式为:

import Ttk

在python3的导入方式则是:

from tkinter import ttk

组件功能的区别

参考资料:http://tktable.sourceforge.net/tile/doc/converting.txt

ttk的关键字参数也有不同,设定一些样式的时候需要用ttk.Style。下面讲一下ttk组件功能的不同。

  • ttk组件共有参数只有:class_, cursor(光标样式), takefocus(是否获取焦点), style(样式)几个参数。
  • 部分组件不支持颜色方面的参数,比如Button不能设置background等参数,而Label等一部分组件仍然支持。
  • 参数不支持缩写,比如-validatecommand不能写成-vcmd,-background不能写成-bg。
  • -state参数不再支持,但是处于兼容的考虑,暂时没有变动这个参数。关于状态设置,ttk.Widget增加了两个相关的方法state和instate。
  • -padx和-pady参数合并为-padding参数,可以提供一个列表表示[左,上,右,下]的内部留白或是一个整数。Label, Button, Frame等组件支持。
  • 单选框和多选框的-indicatoron参数不再受支持,但可以通过把style参数设置为"Toolbutton"来实现按钮式选框。即:
    Checkbutton(style="Toolbutton")
    Radiobutton(style="Toolbutton")
  • 单选框、多选框和按钮的-anchor参数被移除。
  • -compound参数增加了"text"和"image"两个可选值,这么设置分别表示:只显示文本;只显示图片。
  • -bitmap参数被移除。
  • Scale组件不再支持-label参数。如果想要定义带标签的Scale,应使用ttk.LabeledScale组件。
  • 当按下Spinbox组件的上、下调节按钮时,分别会生成两个虚拟事件<<Increment>>和<<Decrement>>。

组件风格的区别

下面的列表中展示了tkinter主模块组件样式,和ttk中相同组件名的组件样式(均使用默认样式)。部分样式没有太大区别的组件没有包括在表格中。当鼠标移动到ttk组件上时,样式会发生变化,比较美观。ttk不是很美观的地方在于激活后,部分组件会出现一个虚线框。

组件名

tkinter主模块中

tkinter.ttk中

Button
Checkbutton
Entry
Menubutton
Radiobutton
Scale (ttk.LabeledScale)
Spinbox

组件状态

ttk.Widget增加了一些特殊的方法,用来操作组件的状态。ttk的状态表示为一个序列,里面包含了多个状态的标志,比如("disabled", "focus")。下面是ttk可以设置的状态标志。如果在不支持某个状态标志的组件上设置了此标志,那么不会有任何效果。

状态 解释
active 光标位于组件之上,且组件可激活,将设置此状态
hover 光标位于组件之上,将设置此状态
disabled 组件处于禁用状态
focus 组件获取焦点,将设置此状态
pressed 按钮被按下,将设置此状态(限于按钮类组件)
alternate 选框的值未被设定时(比如未绑定Checkbutton或Radiobutton到某个Variable),将设置此状态(限于选框类组件)
selected 选框处于启用、选中状态,将设置此状态(限于选框类控件)
background 组件的父窗口是背景窗口(后台窗口),将设置此状态
readonly 组件处于只读状态,禁止用户修改
invalid 当组件验证的值无效,将设置此状态(限于Entry等有validate功能的组件)

如果要表示关闭或没有某个状态,可以在状态标志的前面加上"!"符号,如"!active"表示没有active状态。

state方法用于获取当前的状态元组,如果指定参数,也可以添加设置当前的状态。

ttk.Widget.state(statespec=None)

如下示例:

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

b = Button(root, text="点击")
b.pack()
b.state(["disabled"]) #禁用按钮

mainloop()

需要注意的是:状态中没有normal,如果想要设定成普通的状态,需要通过!符号来关闭。把上面示例的按钮恢复正常可执行b.state(["!disabled"])。state方法用于添加状态,而不是设置!比如,设置状态为"disabled"后再执行b.state(["active"])并不代表当前组件状态变为了["active"],而是["disabled", "active"]。

instate方法则用于检查组件的状态。

ttk.Widget.instate(statespec, callback=None, *args, **kw)

当组件状态符合statespec所指定状态时返回True,否则返回False。如果指定callback,那么符合状态时将会调用这个函数,并将*args, **kw传递给该回调函数。

3.6 ttk.Style

参考资料:tkinter.ttk --- Tk 风格的控件 — Python 3.10.6 文档 -- ttk.Style

ttk.Style可以用于设定组件的样式。在部分组件中,你无法直接设置组件的背景前景色、字体,但可以通过定义Style来达到这个功能。当然,ttk.Style还有更强大的地方。

一般来说一个程序里,只需调用一次ttk.Style即可。可以通过设置ttk组件的style参数,使组件应用指定的Style。

下面是Style类的常用方法,接下来会详细介绍其中的一部分。

方法 作用
configure(style, query_opt=None, **kw) 获取或设置某个样式的基本选项
map(style, query_opt=None, **kw) 获取或设置某个样式的动态选项
lookup(style, option, state=None, default=None) 返回某个样式的option选项值,state是组件的状态序列,用来筛选,default是值缺失时设置的默认值
layout(style, layoutspec=None) 获取或设置style的控件布局属性
element_create(elementname, etype, *args, **kw) 在当前主题下创建一个元素

element_names()

返回当前主题的元素列表
element_options(elementname) 返回指定元素的属性列表
theme_create(theme_name, parent=None, settings=None) 创建一个主题
theme_settings(themename, settings) 将主题临时设为themename并应用settings,然后恢复原来的主题
theme_names() 返回当前主题的列表(包括内置主题)
theme_use(themename=None) 获取或设置当前主题

configure方法

from tkinter import *
from tkinter import ttk

root = Tk()

style = ttk.Style()
style.configure("TButton", foreground="red", font="黑体")

b = ttk.Button(root, text="按钮")
b.pack()

root.mainloop()

创建了一个Style对象后,如上段代码所示,执行了Style.configure方法。这个方法的作用是设置或更改某个组件类的样式。

Style.configure(style, query_opt=None, **kw)

style是样式更改的类名,**kw是设置的参数选项。调用后所有应用style的组件都会变成**kw的指定的参数选项样式。其中**kw参数只能是组件支持的关键字参数,比如background, foreground, relief, font, padding等。如果参数选项是该组件不支持的,不会报错,但是什么效果也没有。

对ttk的组件执行winfo_class()方法,可以获取该组件的类名。ttk的组件的类名十分特殊,ttk.Button的类名不是Button,而是TButton。一般来说,ttk组件的类名是组件名称的title形式(只有首字母大写,比如是TPanedwindow而不是TPanedWindow)前面加上大写T。对于一些支持orient参数的组件,类名还可以是Horizontal.TScale或Vertical.TScale,设置水平状态的style或垂直状态的style。有一个特殊一点的组件Treeview(ttk新增组件,后面介绍),它的类名不是TTreeview,而是不变的,写作Treeview。

类名还可以进行分类。以按钮为例,如果想要做一个红色和一个蓝色前景的按钮,就需要对类名进行分类,不然都是一个样式的。分类的方式是:在类名前面加上Style的分类名称,用句点隔开。定义组件时,用style参数指定该组件使用的分类样式。

from tkinter import *
from tkinter import ttk

root = Tk()

style = ttk.Style()
style.configure("r.TButton", foreground="red", font="黑体")
style.configure("b.TButton", foreground="blue", font="黑体")

b = ttk.Button(root, text="按钮", style="r.TButton")
b.pack()

b = ttk.Button(root, text="按钮", style="b.TButton")
b.pack()

root.mainloop()

configure方法也可以用于查询某个**kw选项的值。需指定query_opt选项。如:查询TButton风格的foreground参数,并赋值给fg,可写作fg = style.configure("TButton", "foreground")

map方法

map方法和configure类似,都是用来获取或设置某个style的样式。但不同的是,map设置的参数是“动态”的,你可以指定设定该style的组件处于某种state的时候参数的值。

Style.map(style, query_opt=None, **kw)

query_opt用来查询,和configure用法一样。下面举一个例子演示一下**kw指定参数和configure的不同。

from tkinter import *
from tkinter import ttk

root = Tk()

style = ttk.Style()
style.configure("TButton", foreground="black")
style.map("TButton", foreground=[("focus", "red"), ("hover", "blue")])

b = ttk.Button(root, text="按钮", style="TButton")
b.pack()

mainloop()

代码段中关于map的这一行是这个意思:如果组件处于"focus"(焦点)状态,那么foreground设为"red",如果组件处于"hover"(鼠标位于上方)状态,那么foreground设为"blue"。如果组件状态为空列表,那么则使用默认的foreground="black"。

这个状态的条件可以指定多个,比如,下面的代码表示,当组件处于"pressed"状态但不处于"focus"状态(!表示否定)的时候改变前景色为"red"。

style.map("TButton", foreground=[("pressed", "!focus", "red")])

注:上面的这行代码中,如果组件设置了takefocus=True,那么"pressed"同时"!focus"的状态是不可能实现的。 但如果设置了takefocus=False,使组件禁止获取焦点,那么鼠标按在按钮上时就可以达到变前景色为"red"的效果。

Element(元素)

ttk的组件可以被划分为多个部分,每个部分称为元素。比如ttk.Menubutton是这个样子的:

通过查询Menubutton的layout(下一节介绍),Menubutton可以被划分为几个元素:label, button, padding, dropbutton。其中label, button, padding是每个组件都可以使用的公用元素。dropbutton是下拉箭头,是Menubutton的专属元素。当我们表示元素的时候,可以用"Menubutton.dropbutton", "Vertical.Scrollbar.uparrow"(指的是Scrollbar组件的上箭头), "这样的写法(注意:此处不是TMenubutton或TScrollbar!)

注:“公用元素”“专属元素”并不属于官方规定的术语,关于元素的知识在ttk文档中没有过多记述,因此找不到一个标准的叫法。

公用元素在任何组件都可以以组件名称来命名,如"Button.label", "Button.button", "Label.label",而专属的元素需要指定父组件,如"Menubutton.dropbutton"而不是"Button.dropbutton"。

下面介绍一下公用的元素。

元素名称 解释
label 表示一个标签,显示文本或图像
button 表示可以点击的按钮
focus 表示组件获取焦点后显示的虚线框,不影响组件焦点设置
padding 表示一个支持内部间隔的框架,此类组件支持-padding参数,表示内部留白

element_create方法用于创建一个自定义元素。

element_create(elementname, etype, *args, **kw)

elementname设置自定义元素的名称,etype是类型,可以是"image"或"from"。

如果etype="image",那么*args需传递 图片对象 和 一系列状态与图片对象组成的元组 ,kw可提供border(图片左、上、右、下的边界), padding(图片内部的留白), sticky(图片对齐方式), width(图片最小宽度), height(图片最小高度)。

如果etype="from",那么*args需传递主题名称(下面介绍)和元素名称(如果不提供将会使用空元素),这会复制给定的元素,此时无需传递kw。

在下一节中,会对这些知识进行应用。

layout方法

layout方法用于获取或设置组件的形态。因为ttk的组件都是由元素构成的,所以我们可以对这些元素进行修改,来设计全新样式的组件。

from tkinter import *
from tkinter.ttk import *
from pprint import pprint #漂亮打印

root = Tk()

style = Style()
pprint(style.layout("TButton"))

通过下面的代码,我们可以获取在"TButton"样式中Button组件的layout样式。 因为打印出的是一个非常复杂的,嵌套了很多列表元组字典的一个列表,所以我使用pprint对打印出的内容进行美化。

下面就来解释一下含义。首先layout的表示方式,是一个列表,可以把这个列表理解为一个Frame。在这个列表中,可以有多个元组,这个元组可以理解为一个元素组件。在这个元组中,第一项是元素的名称,第二项是一个字典代表这个元素的布局属性(也可以是None)。这些属性可以是:side, sticky, children(是一个列表,将元素自身作为一个容器用来排放子元素), unit(0或1,如果设为1,那么这个元素将可以被Widget.identify方法使用。这个方法需传递相对于控件内部的x, y位置,返回位于这个坐标的元素控件名)。

下面是一个示例,演示了如何自定义一个Button。

from tkinter import *
from tkinter.ttk import *

root = Tk()

style = Style()
style.layout("mystyle.TButton", [("Button.button", {"sticky":"nswe"}),
                               ("Button.label", {"sticky":"nswe"})])

Button(root, text="MyTButton", style="mystyle.TButton").pack()

mainloop()

 

因为没有指定side,而是指定了sticky设置四个方向填充,所以按钮和文字组件在同一个地方。

上一节介绍了element_create方法,下面就用这个方法制作一个元素。在处于hover状态,处于focus状态时,样式都会有变化。

from tkinter import *
from tkinter.ttk import *

root = Tk()

img_normal = PhotoImage(file="这是一个按钮.png")
img_hover = PhotoImage(file="鼠标在按钮上.png")
img_focus = PhotoImage(file="按钮获取焦点.png")

style = Style()
style.element_create("ImgEle", "image", img_normal,
                     [["hover"], img_hover],
                     [["focus"], img_focus])
style.layout("mystyle.TButton", [("ImgEle", {"sticky":"nsew"})])

Button(root, text="MyTButton", style="mystyle.TButton").pack()

mainloop()

鼠标移动到按钮上>>> 使按钮获取焦点>>>

这样,当按钮正常状态时会显示:这是一个按钮.png;鼠标移动到按钮上时会显示:鼠标在按钮上.png;点击按钮使其获取焦点会显示:按钮获取焦点.png。 

Theme(主题)

参考资料:TkDocs Tutorial - Styles and Themes

如果将多个对组件样子的设置集中到一起,就形成了主题。计算机系统有一些内置主题,它们是"alt", "default", "clam", "classic"。Mac系统还有一个额外的主题"aqua",Windows则还有"vista", "winxpnative"(或"xpnative")和"winnative"。

theme_use方法用来设置或获取当前主题,主题设置时,会刷新所有的组件,并发送一个虚拟事件<<ThemeChanged>>。下面是不同内置主题的组件样式。

theme_create方法用于自己建立主题。

theme_create(theme_name, parent=None, settings=None)

theme_name是自定义主题的名称,如已经存在将会报错。如果指定parent,那么这个主题的样式会继承父主题,主题设置不更改的地方参照父主题。settings是主题的设置,需传递一个字典,键为组件名称,如TButton,值为此组件的设置。组件的设置也是一个字典,可以包括四个键"configure", "map", "layout"和"element create",所对应的值分别和Style这几个方法期望的格式相同。但是"element create"只能传递一个元素的(etype, *args),不能设置元素名。元素名字默认被设为该组件的名称(如:TButton)。

下面的示例对Button的样式进行了修改。

from tkinter import *
from tkinter.ttk import *

root = Tk()

img_normal = PhotoImage(file="这是一个按钮.png")
img_hover = PhotoImage(file="鼠标在按钮上.png")
img_focus = PhotoImage(file="按钮获取焦点.png")

layout = [("TButton", {"sticky":"nsew"})]
element_create = ("image", img_normal,
                  [["hover"], img_hover],
                  [["focus"], img_focus])

style = Style()
style.theme_create("MyTheme", settings=
                   {"TButton":{
                       "element create":element_create,
                       "layout":layout
                       }
                    }
                   )
style.theme_use("MyTheme")

Label(root, text="Theme: '%s'"%style.theme_use()).pack()
Button(root, text="Button").pack()

mainloop()

3.7 ttk.Combobox

Combobox是文本框和下拉列表框的综合,用户既可以从下拉列表中选取数据,也可以输入文本。Combobox类继承ttk.Entry。

Combobox(master=None, **kw)

ttk的组件参数可能与主模块中有不同的地方,所以公用参数也会进行介绍。

参数 作用
exportselection 这个是所有含有输入功能的组件的共有参数,表示选中的内容是否可以被Misc.selection_get方法检测到,参见对Misc类的介绍
justify 文本在组件内的对齐方式,可以是"left", "center", "right",默认为"left"
width 组件的宽,单位为字符单位
height 组件的高
state 组件的状态,可以是"normal", "disabled", "readonly";"readonly"状态下,只能从下拉列表选取选项,不能输入编辑
values 设置显示在下拉列表中的值(一个序列的形式)
textvariable 与组件的值相关联的Variable
postcommand 当下拉列表弹出时调用的回调函数

常用方法:

方法 作用
current(newindex=None) 将组件的值设为values[newindex],如果不指定newindex,返回当前值在values中的位置,如果不在返回-1
get() 返回组件的值
set(value) 设置组件的值

创建Combobox

from tkinter import *
from tkinter import ttk

root = Tk()

box = ttk.Combobox(root, values=("中文-English", "English-中文"))
box.pack()

mainloop()

虚拟事件<<ComboboxSelected>>

当下拉列表中的内容被选取时,会向Combobox发送一个虚拟事件<<ComboboxSelected>>。

from tkinter import *
from tkinter import ttk

root = Tk()

box = ttk.Combobox(root, values=("中文-English", "English-中文"))
box.pack()
box.bind("<<ComboboxSelected>>", lambda e: print("选取了", box.get()))

mainloop()

3.8 ttk.Separator

Separator组件显示一个分割线的图案,用于美化界面。

Separator(master=None, **kw)

参数 作用
orient 设置分割线的朝向,可以是"horizontal", "vertical",默认是水平

创建Separator

from tkinter import *
from tkinter.ttk import *

def this(): #返回Python之禅的文本
    from this import s
    
    d = {}
    for c in (65, 97):
        for i in range(26):
            d[chr(i+c)] = chr((i+13) % 26 + c)

    return "".join([d.get(c, c) for c in s])

root = Tk()

Label(root, text="The Zen of Python", font=("Arial", 20, "bold")).pack()
Separator(root).pack(fill="x", pady=5) #添加分割线
Label(root, text=this()).pack(padx=5)

mainloop()

可以发现,分割线很好地起到了分隔、美化界面的作用。

3.9 ttk.Sizegrip

Sizegrip组件在屏幕上添加一个拖动柄,用于调节窗口的大小。

Sizegrip(master=None, **kw)

此组件除了来自ttk.Widget的方法外,没有别的参数或方法。

创建Sizegrip

from tkinter import *
from tkinter.ttk import *

root = Tk()

sg = Sizegrip(root)
sg.pack(side="bottom", anchor="e", padx=20, pady=20) #靠左下角排放

mainloop()

3.10 ttk.Notebook

ttk.Notebook管理一个Frame的集合,允许添加多个选项卡,让用户在选项卡之间来回进行切换。

Notebook(master=None, **kw)

参数 作用
width 设置宽
height 设置高
padding 设置内部留白

常用方法:

方法 作用
add(child, **kw) 添加一个新的选项卡
forget(tab_id) 删除tab_id指定的选项卡
hide(tab_id) 隐藏tab_id指定的选项卡
identify(x, y) 返回位于x, y的组件名
index(tab_id) 返回tab_id指定的索引
insert(pos, child, **kw) 在pos索引处插入选项卡
select(tab_id) 选中tab_id指定的选项卡
tab(tab_id, option=None, **kw) 如果指定option,则查询tab_id选项卡的参数;如果指定**kw,则设置选项卡的参数值
tabs() 返回选项卡的Frame列表
enable_traversal()

启用Notebook的快捷键,调用后会为组件添加绑定事件:

<Control-Tab>:选中后一个选项卡

<Shift-Control-Tab>:选中前一个选项卡

<Alt-...>:选中设置了下划线的文字与按键相符的选项卡

创建Notebook

from tkinter import *
from tkinter.ttk import *

root = Tk()

note = Notebook(root)
note.pack()

mainloop()

这段代码创建一个空的Notebook,里面什么内容也没有。

add方法

from tkinter import *
from tkinter.ttk import *

root = Tk()

note = Notebook(root)
note.pack()

f1 = Frame(note)
f2 = Frame(note)
f3 = Frame(note)

Button(f1, text="按钮").pack()
Label(f2, text="标签").pack()

note.add(f1, text="TAB 1")
note.add(f2, text="TAB 2")
note.add(f3, text="TAB 3")

mainloop()

add方法用于在Notebook中添加选项卡,让用户在选项卡之间自由切换。 

add方法需先传递一个父容器为此Notebook的Frame,然后需要设定这个选项卡的参数。可以设定的参数如下。

参数 作用
state 选项卡的状态,可以是"normal", "disabled"(禁用,无法选中), "hidden"(隐藏)
sticky 设置选项卡Frame在Notebook面板内的布局位置
padding 设置组件排放Frame的留白空间
text 设置显示的文本
image 设置显示的图片
compound 图片位于文本的方位
underline 设置文本下划线的位置,如果执行了enable_traversal方法,下划线的文本可以用于Alt快捷键绑定

索引

表示一个Notebook的选项卡,可以有以下方式。

  • 添加的Frame的名称。
  • 0到选项卡总数之间的一个整数。
  • "@x, y"形式来表示。
  • "current"(当前选中页面)和"end"(选项卡数量)。

虚拟事件<<NotebookTabChanged>>

当选项卡的选中变化时,会生成虚拟事件<<NotebookTabChanged>>。

3.11 ttk.Progressbar

Progressbar用于添加进度条控件,可以设置此进度条的值。

Progressbar(master=None, **kw)

参数 作用
orient 设置组件的朝向
length 设置进度条的长度
mode 设置进度条的模式,可以是"determinate"(默认), "indeterminate"
maximum 设置进度条的最大值
value 进度条当前的值
variable 与进度条当前值相关联的Variable

常用方法:

方法 作用
step(amount=None) 将进度条的值增加amount;如不指定amount,默认增加1
start(interval=None) 进度条开始自动增加,每隔interval毫秒增加1;如不指定interval,默认为50毫秒
stop() 停止自动增加

创建Progressbar

from tkinter import *
from tkinter.ttk import *

root = Tk()

bar = Progressbar(root, length=200, maximum=100, value=30)
bar.pack(padx=10, pady=10)

mainloop()

 

上面的代码创建了一个位于30/100位置的进度条。

start和stop方法

start和stop方法分别用于开始和结束进度条的自动增加。当进度条加载完时,会回到开头继续加载。

mode参数

mode参数用于设定进度条的模式。determinate模式下,进度条会不断增加。而indeterminate模式下,进度条会显示成一个小方块,在进度条的槽中来回运动。默认的模式是determinate,效果如下。

indeterminate模式效果如下。

一般,我们在知道进度条要加载的进度时会选用默认的模式,而不知道进度的时候会选用第二种模式。

3.12 ttk.Treeview

Treeview用于添加树状图控件,这个树状图是一个表格的形式,且有层级之分。

Treeview(master=None, **kw)

参数 作用
columns 是一个序列,指定表格中显示的列,序列汇总每个项代表此列的标识名称
height 设置表格的高
padding 设置内部留白
selectmode 设置可以选中的模式,可以是"extended"(多选,默认), "browse"(单选), "none"(无法选择)
show 设置要显示表格哪些部分,可以是"tree"(在#0的位置显示文本标签), "headings"(显示标题行), 也可以是两个组成的列表或空列表。默认是("tree", "headings")表示全部显示

常用方法:

方法 作用
bbox(item, column=None) 返回item数据项相对于Treeview的边界,形式为(x, y, width, height),如指定column,则返回此单元格边界
get_children(item=None) 返回item的子数据项列表,如果不指定item则返回最顶级的数据项列表
set_children(item, *newchildren) 用newchildren替换item的子数据项
column(column, option=None, **kw) 查询或修改某一列的参数选项
delete(*items) 删除item数据项以及子数据项
detach(*items) 将items数据项隐藏
exists(item) 判断item数据项是否在Treeview中
focus(item=None) 将item数据项设为当前焦点,如不指定item则返回当前焦点数据项,如无焦点则返回空字符串
heading(column, option=None, **kw) 查询或修改column数据列的参数选项
identify(component, x, y) 返回x, y位置上component数据项的描述信息,如无则返回空字符串
identify_row(y) 返回y位置上的数据项
identify_column(x) 返回x位置上的数据列
identify_region(x, y) 返回x, y位置上的类型,返回值有:"heading"(标题栏), "separator"(标题之间的分割线), "tree"(树的区域), "cell"(单元格)(Tk 8.6可用)
identify_element(x, y) 返回位于x, y的数据项(Tk 8.6可用)
index(item) 返回item位于其父项的子项列表中的索引
insert(parent, index, iid=None, **kw) 插入数据项
item(item, option=None, **kw) 查询或修改item数据项的参数选项
move(item, parent, index) 将item数据项移动到parent父项的index位置
next(item) 返回item项的下一项,如果此项为其父项的最后一个子项,则返回空字符串
parent(item) 返回item项的父项,如果为最顶级数据项则返回空字符串
prev(item) 返回item项的上一项,如果此项为其父项的第一个子项,则返回空字符串
see(item) 滚动Treeview使item数据项可见
selection(item) 返回所有选中项
selection_set(*items) 使items成为新的选中项
selection_add(*items) 将items加入选中项
selection_remove(*items) 从选中项中移除items
selection_toggle(*items) 切换items各项的选中状态
set(item, column=None, value=None) 如指定item,则返回item的{列:单元格值, ...}字典;如指定两个参数,返回此单元格的值;如指定三个参数,则设置此单元格的值
tag_bind(tagname, sequence=None, callback=None) 对tag进行事件绑定
tag_configure(tagname, option=None, **kw) 对含有指定tag的数据项的参数选项进行查询或设置,**kw参数可以设置foreground, background, font, image(当数据项图片为空时)
tag_has(tagname, item=None) 如指定item,根据item是否有指定tag返回1或0;如不指定,则返回设置了指定tag的所有数据项

Treeview继承XView和YView,所以还支持两个方向的滚动条方法。 

创建Treeview

from tkinter import *
from tkinter.ttk import *

root = Tk()

tree = Treeview(root, columns=("A", "B", "C"))
tree.pack()

mainloop()

这段代码创建了一个Treeview,有三个列,名字分别为"A", "B", "C"。 实际运行时,除了这三列,在所有列的前面还多了一列,是Treeview的文本标签列。隐藏文本标签列,可以设定show参数。

如果要访问列,可以使用索引或者列的名字。文本标签列的索引是"#0",后面的列依次为"#1", "#2", "#3"……即使隐藏了文本标签列,后面的列的索引依然不会变化。因为在指定Treeview时columns参数设置了列的名字,所以后面的列也可以用"A", "B", "C"来表示。

heading方法

heading方法用于查询或修改标题栏。首先需提供这一列的索引或名字,然后指定需要获取或设置的参数。可以指定的参数有:

参数 作用
text 列的标题的文本
image 列标题的图片(显示于文本右侧)
anchor 对齐方式锚点
command 点击标题执行的回调函数
from tkinter import *
from tkinter.ttk import *

root = Tk()

tree = Treeview(root, columns=("A", "B", "C"))
tree.pack()

tree.heading("#0", text="文本标签")
tree.heading("#1", text="A列") # "#1"也可换成"A"
tree.heading("#2", text="B列")
tree.heading("#3", text="C列")

mainloop()

insert方法

insert方法用来插入项目,一个数据项代表一行。

Treeview.insert(parent, index, iid=None, **kw)

parent指定项目的父项,由于Treeview是可以分层的,所以可能有项目层级的嵌套;如果是顶层的项目,可以将parent设为空字符串。index指定插入的位置,可以是一个整数索引或者"end"。iid指定此项目的标识符,如果想要对项目进行访问,需要提供项目的iid;iid不能和之前定义过的iid相重复;可以从方法列表中看到,很多方法都需要提供item参数,item代表的正是项目的iid。**kw参数如下:

参数 作用
text 文本标签栏处显示的文本
image 文本标签栏显示的图片(在文本左侧)
values 指定每列单元格的值,是一个序列,应与columns参数指定的列数相同
open 是否显示此数据项的子项
tags 与该数据项关联的tag列表

insert方法执行后返回添加的数据项的iid。

from tkinter import *
from tkinter.ttk import *

root = Tk()

tree = Treeview(root, columns=("A", "B", "C"))
tree.pack()

tree.heading("#1", text="A")
tree.heading("#2", text="B")
tree.heading("#3", text="C")

tree.insert("", "end", text="1", values=("A1", "B1", "C1"))
tree.insert("", "end", text="2", values=("A2", "B2", "C2"))

mainloop()

如下是分层级的Treeview示例:

from tkinter import *
from tkinter.ttk import *

root = Tk()

tree = Treeview(root, columns=("A", "B", "C"))
tree.pack()

tree.heading("#1", text="A")
tree.heading("#2", text="B")
tree.heading("#3", text="C")

tree.insert("", "end", iid="1", text="1", values=("A1", "B1", "C1")) #设置iid="1"
tree.insert("1", "end", text="2", values=("A2", "B2", "C2")) #设置父项为iid="1"的项目

mainloop()

运行后出现一个加号,点击加号可以打开子项。

虚拟事件

Treeview组件会引发如下虚拟事件:

事件 条件
<<TreeviewSelect>> Treeview的选中项目改变
<<TreeviewOpen>> 当焦点所在项的子项展开(open=True)
<<TreeviewClose>> 当焦点所在项的子项合并(open=False)

3.13 tkinter.font

tkinter.font模块中提供了一些关于字体的操作。首先要介绍的是font.Font类,这个类指定一个类型的字体,这个类的字符串形式可以被直接传递给组件的-font参数。

可以提供以下关键字参数:

参数 作用
font 指定字体样式,可以是一个字体名或者字体元组,如("宋体", 12)
name 此类字体的名称,指定后可以传递给组件font="MyFontName"
exists 字体是否已经存在于系统,如果设置为True而字体并不存在,则报错

还可以提供下面的关键字参数,这组参数和上面的参数font, exists(name除外)不用重复指定: 

参数 作用
family 字体名称,如"宋体", "黑体", "Arial", "Times"
size 字体尺寸大小
weight 字体的厚度,可以是"normal"(普通), "bold"(加粗)
slant 字体的倾斜样式,可以是"roman"(无倾斜), "italic"(倾斜)
underline 是否有下划线
overstrike 是否有删除线

示例如下: 

from tkinter import *
from tkinter import font
        
root = Tk()
f = font.Font(family="黑体",
              size=16,
              slant="italic",
              underline=True)

Label(root, text="Tip:这是一段文字", font=f).pack()

mainloop()

Font类还支持如下方法:

方法 作用
copy() 将当前字体复制,返回一个Font对象
actual(option=None, displayof=None) 返回字体的属性信息,如不指定option,返回值如:{'family': '黑体', 'size': 16, 'weight': 'normal', 'slant': 'italic', 'underline': 1, 'overstrike': 0}
cget(option) 返回字体的option属性信息,相当于font.actual(option=option)

config(**option)

更改字体的选项
measure(text, displayof=None) 返回text字符串使用此字体时的文本宽度(像素)
metrics(*options, **kw) 返回字体的度量信息,如不指定options,返回值如:{'ascent': 18, 'descent': 3, 'linespace': 21, 'fixed': 1}

 除了Font类,font模块还提供了两个方法。

方法 作用
families(root=None, displayof=None) 返回系统上所有的可用字体名称
names(root=None) 返回自定义的字体名称

当调用names()方法的时候,我们会发现tk有一些预定义的字体,也可以使用它们:

('fixed', 'oemfixed', 'TkDefaultFont', 'TkMenuFont', 'ansifixed', 'systemfixed', 'TkHeadingFont', 'device', 'TkTooltipFont', 'defaultgui', 'TkTextFont', 'ansi', 'TkCaptionFont', 'system', 'TkSmallCaptionFont', 'TkFixedFont', 'TkIconFont')

3.14 tkinter.scrolledtext

scrolledtext模块中提供了一个ScrolledText类,继承自Text。和Text不同的是,这个组件在外观上多了一个y方向的滚动条。其他使用方法与Text一致。如果想要制作带有滚动条的Text,使用这个组件可以方便许多。

3.15 更多子模块

以上介绍的这些子模块都是最为常用的。除了这些以外,tkinter还有以下子模块。

子模块 描述
commondialog 提供了调用tk对话框的基类;功能已被messagebox, filedialog等替代
dialog 提供了一个对话框,可设置标题,提示语,按钮等;样式较为简陋
dnd 用于实现组件拖拽移动功能;该模块是实验性的,后期会被替代
simpledialog 提供了一些询问字符串、整数等类型的对话框;样式较为简陋,而且是英文版的
tix 提供了一些拓展组件;如今比较过时,可用ttk替代

附录1 关于tkinter的网站

Python官网(tkinter模块):tkinter —— Tcl/Tk 的 Python 接口 — Python 3.10.5 文档https://docs.python.org/zh-cn/3/library/tkinter.html#module-tkinterhttps://docs.python.org/zh-cn/3/library/tkinter.html#module-tkinter

Python tkinter源代码的github:cpython/Lib/tkinter at 3.10 · python/cpython · GitHubThe Python programming language. Contribute to python/cpython development by creating an account on GitHub.https://github.com/python/cpython/tree/3.10/Lib/tkinterhttps://github.com/python/cpython/tree/3.10/Lib/tkinter

Tcl/Tk主页:Tcl Developer Sitehttps://www.tcl.tk/https://www.tcl.tk/

Tk教程文档主页:TkDocs HomeTkDocs features tutorials and other material for modern Tk GUI development, using Python/Tkinter, Tcl, Ruby, and Perl/Tkx.http://tkdocs.com/http://tkdocs.com/

附录2 调用Tcl/Tk命令

Tcl是一种解释型脚本语言,并不包含窗口GUI的操作。Tk是Tcl的GUI图形扩展,以Tcl语言为基础,提供了大量的组件和窗口操作。如果Tcl/Tk没有Tk,那么就只有空的语法,只有赋值、判断、循环这些基础操作,无法创建窗口。

如果要创建一个Tcl/Tk解释器,只需要用Tk类就可以。Tk创建一个顶层窗口,也会创建一个新的Tcl/Tk解释器。它和Toplevel的不同点就在于Tk会创建新的解释器,而Toplevel不会。

如果不需要使用Tk,只使用Tcl的语法,那么可以在Tk类的参数设置useTk=0,也可以使用Tcl函数。Tcl函数返回一个useTk=0的Tk对象。如下:

tcl = Tk(useTk=0)
tcl = Tcl()
#不使用tk

如果设置了useTk=0,那么不能使用与Tk相关的任何方法。

Tk类里面有一个实例变量tk,是_tkinter.tkapp对象(tkinter前面加一个下划线,是tkinter的内建模块,是用Tcl/Tk编写,里面定义了TclError, Tcl_Obj, TkappType几个对象),它有一些方法,能够调用Tcl/Tk的命令。这些方法,也可以直接作为Tk或其他组件对象的方法调用。

方法 作用
call(...) 在Tcl解释器中执行Tcl/Tk命令,需提供一系列在Tcl语言中用空格隔开的命令作为参数,如果是命令用字符串代替,如:一段Tcl命令set num 2可写成tk.call("set", "num", 2)
createcommand(name, func) Create a name procedure in the Tcl interpreter (there is no function in the Tcl language, but there is a concept of command or procedure, which is equivalent to a function in Python), which has the function of func function
deletecommand(name) Delete name procedure in Tcl interpreter
eval(script) Execute the script command in the Tcl interpreter (script is a string)
evalfile(fileName) Run the tcl program file (*.tcl) in the Tcl interpreter
getvar(name) Returns the value of the variable named name in the Tcl interpreter
setvar(name, value) Define a variable named name in the Tcl interpreter with a value of value
unsetvar(name) Delete variable named name in Tcl interpreter
mainloop()

Enter the main loop

Examples are as follows:

from tkinter import *

root = Tk()

button = Button(root, name="busyButton", text="BUSY...")
button.pack()
root.call("tk", "busy", "hold", ".busyButton")

Button(root, text="cancel", command=lambda: root.call("tk", "busy", "forget", ".busyButton")).pack()

root.mainloop()

This example uses tk's busy to keep the component in a busy state that cannot receive events, see

Section 8 of some very flexible uses of Python tkinter and utility functions .

Appendix 3 Color List

Due to space limitations, this section is appended to the following article. A total of 760 colors supported by Tk are sorted out.

Tk color style, color name, RGB value, list of hexadecimal values ​​- Python zzy's Blog - CSDN Blog

If you encounter problems when developing Python tkinter programs, or have suggestions for article content, you can contact me by private message, thank you for your support!

Guess you like

Origin blog.csdn.net/qq_48979387/article/details/125768994