Python tkinter(GUI编程)模块最完整讲解(中)

发布于:2023-01-24 ⋅ 阅读:(2452) ⋅ 点赞:(2)

上一篇:Python tkinter(GUI编程)模块全解(上)_Python zzy的博客-CSDN博客

2 tkinter主模块

2.10 Checkbutton

Checkbutton即多选框,用户可以勾选或取消勾选。Checkbutton可以绑定一个variable,一般是BooleanVar。Checkbutton拥有Button的参数之外,还可以有一些别的参数。

参考资料:Python ---(三)Tkinter窗口组件:Checkbutton_近视的脚踏实地的博客-CSDN博客

Checkbutton(master=None, **kw)

参数 作用
variable 与Checkbutton选择相关的Variable
onvalue 多选框选中时variable的值,默认为1
offvalue 多选框未选中时variable的值,默认为0
selectcolor 选择方框的颜色
selectimage 选中时的图片(须指定image参数)
indicatoron 是否显示为勾选框样式,默认为True

常用方法: 

方法 作用
select() 选中多选框
deselect() 取消选中选框
toogle() 切换选框的选中状态(反选选框)
invoke() 调用Checkbutton的command(disabled无效)
flash() 使Checkbutton闪烁几次(在normal和active几次切换)

创建Checkbutton

from tkinter import *

root = Tk()
root.geometry("200x200")

def tg():
    print("选中/取消选中")

cb = Checkbutton(root, text="toogle", command=tg)
cb.pack()

mainloop()

 

可以尝试点击Checkbutton,左边的方框就会打上勾或取消打勾。每次选择后都会打印"选中/取消选中"。

variable参数

from tkinter import *

root = Tk()
root.geometry("200x200")

def tg():
    print("当前状态为:", cb_var.get())

cb_var = BooleanVar()
cb = Checkbutton(root, text="toogle", command=tg, variable=cb_var)
cb.pack()

mainloop()

把多选按钮绑定到一个Var上,这样就可以获取Checkbutton的值。

indicatoron参数

Checkbutton有两种样式,一种是上面的勾选框样式,还可以设置为一个按钮盒的样式。默认是显示为勾选框的样式,如果把indicatoron设置为False也可以设置为按钮的样式。

from tkinter import *

root = Tk()
root.geometry("200x200")

cb = Checkbutton(root, text="toogle", indicatoron=False)
cb.pack()

mainloop()

 选中状态>>>

2.11 Radiobutton

与多选框相对应,Radiobutton是单选框。多个单选框可以绑定一个variable,这个variable的值是选中的单选框的值。

参考资料:Python ---(四)Tkinter窗口组件:Radiobutton_近视的脚踏实地的博客-CSDN博客

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

Radiobutton的参数和Checkbutton几乎完全一样,不同的是Radiobutton没有onvalue和offvalue这两个参数,而是由value这个参数代替。value参数的作用是:指定单选框选中时绑定的Var的值。

常用方法和Checkbutton介绍的几个基本一样,但是没有toogle方法。

创建Radiobutton

一般情况下Radiobutton会出现多个,而Checkbutton只出现一个。

from tkinter import *

root = Tk()
root.geometry("200x200")

var = StringVar()
var.set("A")

Radiobutton(root, text="A. Python", variable=var, value="A").pack()
Radiobutton(root, text="B. C", variable=var, value="B").pack()
Radiobutton(root, text="C. Java", variable=var, value="C").pack()

mainloop()

上面的三个单选框,都绑定了一个variable,还指定了一个value参数。当variable的值被设为单选框的value,那么这个选框将是选中的状态。当点击单选按钮,variable的值就被设为这个单选按钮的值。因为variable的值只能有一个,所以你只能在绑定该variable的单选按钮里面选中一个单选按钮。

2.12 Menu

Menu也就是菜单,菜单一般有两种,一种是窗口上的菜单,一种是弹出式菜单。

参考资料:Python ---(十三)Tkinter窗口组件:Menu_近视的脚踏实地的博客-CSDN博客 

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

参数 作用
tearoff 是否允许用户分离菜单,默认为True
title 分离菜单的标题
tearoffcommand 用户分离菜单时执行的事件
postcommand 菜单被打开时执行的事件

常用方法:

方法 作用
add(itemType, **kw) 添加一个菜单项,itemType是command, cascade, checkbutton, radiobutton, separator之一
insert(index, itemType, **kw) 在index位置插入菜单项
add_command(**kw) 添加命令菜单项
add_cascade(**kw) 添加分层菜单项
add_checkbutton(**kw) 添加多选框菜单项
add_radiobutton(**kw) 添加单选框菜单项
add_separator(**kw) 添加菜单分割线
delete(index1, index2=None) 删除位于index1(到index2之间)的菜单项
entrycget(index, option) 获取位于index菜单项的option值
entryconfig(index, **kw) 更改位于index菜单项的参数的值
post(x, y) 在(x, y)位置弹出菜单
unpost() 取消弹出菜单
invoke(index) 执行位于index菜单项的command,如果菜单项是单选框或多选框,则选中它们。
type(index) 返回位于index菜单项的类型,是command, cascade, checkbutton, radiobutton, separator之一

创建窗口菜单

from tkinter import *

root = Tk()

menubar = Menu(root)
root.config(menu=menubar) #把菜单绑定root

mainloop()

这样,我们就成功创建出一个菜单,并且绑定了显示的窗口。不过这样的菜单什么都没有,接下来我们要在菜单中添加菜单项。

add方法

add方法可以添加菜单项。第一个参数itemType指定菜单项的类型,马上会介绍到。add(itemType)也可以被add_itemType()所替换。你还可以提供如下参数**kw(activebackground, activeforeground, bg, fg由于之前的组件介绍过,这里不介绍了):

参数 作用
accelerator 显示菜单的补充说明标签
label 菜单项显示的标签
font 标签的字体
bitmap 菜单项显示的位图
image 菜单项显示的图片
compound 图片显示于标签的方位
state 菜单项的状态
underline 在标签的第几个索引的字符处画下划线,用来绑定Alt快捷键
columnbreak 从此菜单项开始另起一列显示
hidemargin 菜单项长度适应label长度,默认为True
command 点击菜单项时执行的回调函数
menu 绑定的分层子菜单(add_cascade)
selectcolor 单选或多选按钮菜单的selectcolor
selectimage 单选或多选按钮菜单的selectimage
value 单选按钮菜单的value
variable 单选或多选按钮菜单绑定的variable
onvalue 多选按钮菜单的onvalue
offvalue 多选按钮菜单的offvalue

add_command方法

menu.add_command(**kw)相当于menu.add("command", **kw)

add_command方法在菜单中添加一个命令菜单项。它有如下参数:

下面, 让我们给菜单创建一个命令,点击时打印一段文字。

from tkinter import *

root = Tk()

menubar = Menu(root)
root.config(menu=menubar)

menubar.add_command(label="Click", command=lambda:print("Hello"))

mainloop()

 点击菜单的Click按钮,就会执行print("Hello")

add_cascade方法

菜单可以有层级之分。最上层的菜单就是绑定了root的菜单,下面可以有一些子菜单,继承绑定窗口的父菜单,实现分层效果。

from tkinter import *

root = Tk()

menubar = Menu(root)
root.config(menu=menubar)

filemenu = Menu(menubar)
filemenu.add_command(label="Save", command=lambda:print("OK!"))

menubar.add_cascade(label="File", menu=filemenu)

mainloop()

首先需要创建一个菜单,继承绑定窗口的菜单menubar,然后添加这个子菜单的项目。接着,需要把这个子菜单添加到父菜单中,需要提供一个menu参数指定添加的子菜单。

子菜单也可以有子菜单。如下示例:

from tkinter import *

root = Tk()

menubar = Menu(root)
root.config(menu=menubar)

filemenu = Menu(menubar)
savemenu = Menu(filemenu)

menubar.add_cascade(label="File", menu=filemenu)
filemenu.add_cascade(label="Save", menu=savemenu)

savemenu.add_command(label="save1")
savemenu.add_command(label="save2")

mainloop()

分离菜单

当我们点击菜单上的虚线,可以跳出一个工具窗口,这就是分离菜单。

分离菜单功能有很多问题,并且大多数应用都没有这个功能,建议大家把它禁用。如果想要禁用分离菜单功能,可以在定义Menu的时候把tearoff参数设置为False。

Menu(menubar, tearoff=False)

accelerator参数

accelerator可以对菜单项进行补充。一般这个参数指定的是一个加速键(快捷键)名称,比如Ctrl+N这种。

不过,即使指定了accelerator参数也没有真正的绑定快捷键,需要使用bind来进行绑定。

from tkinter import *

root = Tk()

menu = Menu(root)
root.config(menu=menu)

def new(event=None):
    print("New file")

fm = Menu(menu)
menu.add_cascade(label="File", menu=fm)    
fm.add_command(label="New", accelerator="Ctrl+N", command=new)

root.bind("<Control-n>", new)

mainloop()

按下Ctrl-N或点击菜单,执行new函数。

underline参数

underline参数指定一个索引,绑定一个Alt快捷键。指定了underline的菜单项可以快捷触发。触发方式是:先按下Alt,然后下划线会显示出来,再按下菜单项标签下划线上的字符即可执行这个菜单项。

from tkinter import *

root = Tk()

menu = Menu(root)
root.config(menu=menu)

def new():
    print("New file")

menu.add_command(label="New", underline=0, command=new)

mainloop()

激活并按下Alt>>>按下n键>>>

add_separator方法

add_separator方法可以给菜单添加一条分割线。

from tkinter import *

root = Tk()

menu = Menu(root)
root.config(menu=menu)

fm = Menu(menu, tearoff=False)
menu.add_cascade(label="File", menu=fm)

fm.add_command(label="New File")
fm.add_command(label="Save")
fm.add_separator() #添加分割线
fm.add_command(label="Exit")

mainloop()

分割线常用于分隔不同类的菜单项,比如编辑器中,打开文件、保存文件、退出几个文件操作类别都用分隔线隔开。

弹出菜单

如果要弹出菜单,那么不需要绑定到窗口(root.config(menu=menu)),当然绑定也没关系。弹出窗口需要使用post方法,需要提供x, y两个参数。但这两个参数必须是屏幕上的位置,x_root和y_root。

下面的示例:当右击鼠标时在鼠标处弹出菜单。

from tkinter import *

root = Tk()

menu = Menu(root)

def show(event):
    menu.post(event.x_root, event.y_root)
    
def cp():
    print("Copy")

menu.add_command(label="Copy", underline=0, command=cp)

root.bind("<Button-3>", show)

mainloop()

2.13 Menubutton

Menubutton是一个Button的样式,可以绑定一个菜单,点击后弹出菜单。这个组件比较老,现在可以用Menu实现Menubutton的功能了,不过Menubutton在某些情况下要更简单好用一些。

参考资料:Python ---(十四)Tkinter窗口组件:Menubutton_近视的脚踏实地的博客-CSDN博客

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

参数和Button基本一样,但是没有command,还有一些其他的参数。

参数 作用
menu 绑定一个菜单
direction 位于按钮的菜单弹出方位,有"left"(左),"right"(右),"above"(上),"below"(下),默认是below

创建Menubutton

from tkinter import *

root = Tk()

mb = Menubutton(root, text="弹出")
mb.pack()

menu = Menu(mb)
def cp():
    print("Copy")
menu.add_command(label="Copy", command=cp)

mb.config(menu=menu)

mainloop()

 点击按钮>>>

需要注意的是,继承关系不要弄错。绑定到Menubutton的菜单的master必须是该Menubutton,否则菜单跳不出来。 

2.14 组件基类

现在,你已经学习了一部分组件。在学习更多组件之前,先要详细介绍一下组件的基类。在tkinter(Python)中,大多数组件都有共用的方法,这是因为它们都继承共同的类。如果你想自己了解一下继承关系,可以看Lib/tkinter/__init__.py。

在这些类中,有一些方法的参数默认为None,这意味着如果为None可以返回当前参数设定的值。

Misc类

这个类是模块中最基本的类,所有组件甚至是Tk都继承这个类。不过,组件并不直接继承这个类,而是继承Widget类(Widget类直接继承BaseWidget类,而BaseWidget类直接继承Misc),比较特殊的Toplevel继承的是BaseWidget类。

after(ms, func=None, *args)

等待ms毫秒(1s=1000ms)后执行func,并将所需参数通过args传递给func函数。常用于循环执行函数。

from tkinter import *

root = Tk()

def call(timer):    
    timer -= 1
    print(timer)

    root.after(1000, call, timer)

call(5)

mainloop()

如上示例,首先调用了一次call方法,在call方法里面将timer减去1,然后等待1秒后,将timer减去1后的值传递给call函数,然后在call函数里面再减一。每隔一秒就会打印一个数字。

after_cancel(id)

after方法返回一个标识符,可以传递给after_cancel方法取消after执行。

from tkinter import *

root = Tk()

def call(timer):    
    timer -= 1
    print(timer)

    id = root.after(1000, call, timer)
    if timer <= 0:
        root.after_cancel(id)

call(5)

mainloop()

如果检测到timer <= 0,after将会被取消,call函数也不会再执行。只有在after处于等待状态时,after_cancel才有效。

bell()

响铃一次,可参考Python tkinter一些十分灵活的运用方式和实用函数的第四节。

bind(sequence=None, func=None, add=None)

绑定事件。详见上一篇。

bind_all(sequence=None, func=None, add=None)

窗口所有组件绑定事件。详见上一篇。

bindtags(tagList=None)

设置事件执行的顺序。详见上一篇。

cget(key)

返回组件的key参数的值。如:label.cget("text")获取label的text参数值。

clipboard_append(string)

将string添加复制到剪贴板,复制的内容会被添加到上一次复制的内容后面。如果想要复制string,需先执行clipboard_clear()。

clipboard_clear()

清空剪贴板。

clipboard_get()

获取复制的内容。

config = configure(cnf=None, **kw)

更改组件的参数。cnf上一篇介绍过,和**kw一样可以用来传递参数,不过传递给cnf的是一个字典。

destroy()

销毁组件。窗口类也有这个方法,但是继承于Wm。

event_generate(sequence, **kw)

生成虚拟事件。详见上一篇。

focus = focus_set()

使窗口的输入焦点指向该组件。如果窗口未激活,这个组件将在用户激活窗口后作为该窗口的输入焦点。

focus_force()

使组件直接获取焦点,窗口将自动激活。和focus_set不同的是,focus_set不会自动激活窗口。

focus_get()

返回获取焦点的子组件。如果窗口未被激活,那么将返回None。

focus_lastfor()

返回窗口激活后将获取焦点的子组件。和focus_get不同的是,focus_lastfor即使没有激活窗口,也会返回将在激活后获取焦点的子组件。

grab_release()

释放组件焦点抓取。

grab_set()

设置组件焦点抓取。使焦点永远保持在这个组件上,在释放抓取之前不能转移焦点,只能在这个组件上操作。如果应用在窗口上,那么只能在这个应用程序的这个窗口上进行操作,无法操作其他的窗口(只能拖拽移动)。

image_names()

获取组件内可以应用的所有的图像名称,是Tcl内部的名称字符串。

keys()

返回组件所有的可设置参数列表。

lift = tkraise(aboveThis=None)

将窗口堆叠顺序抬升。如果不指定aboveThis,则窗口置于此应用程序所有窗口的最上方。如果指定aboveThis,则窗口置于aboveThis窗口的上方。

lower(belowThis=None)

将窗口堆叠顺序下降。如果不指定belowThis,则窗口置于此应用程序所有窗口的最下方。如果指定belowThis,则窗口置于belowThis窗口的下方。

nametowidget(name)

返回名为name的子组件。比如定义了一个Button(root, name="MyButton"),可以通过root.nametowidget("MyButton")返回Button对象本身。如果不会产生混淆,可以只提供组件本身的名字,不用提供组件的完整名称。

selection_clear()

清除子组件的选中内容。

selection_get(**kw)

获取子组件中的选中内容,如没有则会报错。如果某个输入类组件设定了exportselection=False,那么在这个组件上的选中内容不会被检测到。

unbind(sequence)

解除绑定。详见上一篇。

unbind_all(sequence)

解除bind_all的绑定。

update()

在事件循环中刷新,并刷新用户的动作引起的事件。

update_idletasks()

在事件循环中刷新,但不会处理用户动作引起的事件。

quit()

该组件退出事件循环(mainloop),但不销毁本身。

wait_variable(name="PY_VAR")

一直阻塞直到variable改变。详见Python tkinter一些十分灵活的运用方式和实用函数第5节。

wait_visibility(window=None)

一直阻塞直到window可见性改变。详见Python tkinter一些十分灵活的运用方式和实用函数第5节。

wait_window(window=None)

一直阻塞直到window销毁。详见Python tkinter一些十分灵活的运用方式和实用函数第5节。

winfo_children()

返回该组件的子组件列表。

winfo_class()

返回该组件的类名。比如Entry组件的类名是"Entry"。

winfo_containing(rootX, rootY)

返回位于电脑屏幕rootX, rootY的子组件。

winfo_exists()

返回组件是否存在。如果组件存在返回1,不存在(被destroy)返回0.

winfo_geometry()

返回组件的geometry信息(需要先映射组件,否则不准),返回格式为widthxheight+x+y。注:不是设置!

winfo_height(), winfo_width()

分别返回组件的高和宽(需要先映射组件,否则不准),会随着窗口的改变而更新。

winfo_reqheight(), winfo_reqwidth()

分别返回组件定义时的高和宽(不需要映射组件),不会随着窗口的改变而更新。

winfo_id()

返回窗口绘制组件区域(也就是整个窗口中,除去标题和菜单栏部分)的标识符,是一个整数。可以用这个方法返回Windows Tk窗口内部绘制组件区域的句柄,(注意:不是整个tk窗口!参见winfo_frame)

winfo_frame()

返回窗口的标识符,是一个十六进制字符串。可以用这个方法返回Windows Tk窗口的句柄。

winfo_name()

返回组件的Tcl内部名称。也可以用str(widget)代替这一句。

winfo_parent()

返回组件的父组件。

winfo_pointerx(), winfo_pointery(), winfo_pointerxy()

分别返回鼠标在屏幕上的x位置,y位置,以及x,y位置的元组。

winfo_rootx(), winfo_rooty()

分别返回组件在屏幕上的x位置,y位置(需要先映射组件,否则不准)。

winfo_screenheight(), winfo_screenwidth()

分别返回屏幕的高和宽。

winfo_x(), winfo_y()

分别返回组件在父容器上的x位置,y位置(需要先映射组件,否则不准)。

winfo_rgb(color)

返回组件中名为color的颜色的RGB色彩值。返回的是一个三个值的元组,每个值介于0和65535之间。

winfo_server()

返回屏幕的服务器信息。如:Windows 10.0 18363 Win64

注:使用winfo系列方法返回组件尺寸信息的时候,必须要在组件映射或update之后才能有效调用。mainloop方法就是在循环update窗口以及里面的组件,所以在调用mainloop后不需要执行update,但在mainloop之前需要执行update。但是winfo_reqwidth(), winfo_reqheight()不需要。

Wm类

参考资料:Toplevel顶级窗口和Tk根窗口方法汇总_近视的脚踏实地的博客-CSDN博客

WM是Window manager(窗口管理器)的缩写,所有窗口类继承Wm,也就是Tk和Toplevel。Wm类的方法以wm_作为开头,比如wm_destroy, wm_attributes,不过我们也可以写作destroy, attributes。在tk类中有很多这样的多名字的方法,这是因为类中对一些方法重命名过。

下面介绍Wm类(Tk和Toplevel)的方法。

注:由于方法过多,这里只筛选出可能有用的方法进行详细的解析。其他方法可见参考资料

aspect(minNumer=None, minDenom=None, maxNumer=None, maxDenom=None)

控制窗口的宽高比,使宽高比限制在:minNumer / minDenom ~ maxNumer / maxDenom。如果不设置参数,则返回这四个参数的元组。

attributes(*args)

设置窗口的各项属性。可以提供一个参数,是属性名称,将会返回窗口的属性值。如果再提供一个参数,则设置这个窗口的属性值。选项提供时,需要在前面加上一个-符号,比如:root.attributes("-alpha", 0.5)表示设置窗口半透明。

窗口的属性选项有:

选项 作用 系统
alpha 设置窗口的不透明度,是一个0-1的浮点数,1.0表示不透明,0.0表示完全透明。 Windows, Mac
disabled 窗口是否禁用,禁用时无法在窗口上进行任何操作 Windows
fullscreen 窗口是否全屏,全屏和最大化不同,全屏时窗口最大的同时标题栏会隐藏。 Windows, Mac
modified 窗口是否标记为改动过 Mac
titlepath 设置窗口代理图标的路径 Mac
toolwindow 窗口是否设置为工具窗口样式,可以参考Python tkinter一些十分灵活的运用方式和实用函数的第一节。 Windows
topmost 窗口是否始终置顶显示 Windows, Mac
transparentcolor 设置穿透颜色,可以参考Python tkinter一些十分灵活的运用方式和实用函数的第三节。 Windows

deiconify()

显示窗口(和withdraw方法相反)。

geometry(newGeometry=None)

设置窗口尺寸,newGeometry格式有以下几种:

  • "%dx%d"%(width, height):设置窗口的宽和高。
  • "+%d+%d"%(left, top):设置窗口与屏幕左边、上边的距离。
  • "+%d-%d"%(left, bottom):设置窗口与屏幕左边、下边的距离。
  • "-%d-%d"%(right, bottom):设置窗口与屏幕右边、下边的距离。
  • "-%d+%d"%(right, top):设置窗口与屏幕右边、上边的距离。
  • "":设置为空字符串,表示窗口大小适应内部组件大小。
  • 也可以将窗口宽高与窗口偏移距离结合使用,如"100x100+50-30"表示:窗口大小100x100,与屏幕左边相隔50像素,与屏幕下边相隔30像素。

iconbitmap(bitmap=None, default=None)

设置窗口图标为bitmap(是一个ico文件的路径字符串),如果设置default(一个文件名),那么该窗口的子窗口将自动设置图标为此图标文件。

iconify()

使窗口最小化。

iconphoto(default=False, *args)

设置窗口图标。如果default设置为True,那么该窗口的子窗口将自动设置图标为此图标文件。*args可以提供图标,提供的是PhotoImage对象。

maxsize(width=None, height=None)

设置窗口可以被拖拽的最大宽和高。

minsize(width=None, height=None)

设置窗口可以被拖拽的最小宽和高。

overrideredirect(boolean=None)

设置是否隐藏窗口的标题栏和边框。隐藏标题栏的窗口:

protocol(name=None, func=None)

当窗口检测到name协议的时候,执行func。协议是窗口管理器和应用的通信方式。最常用的协议是WM_DELETE_WINDOW,当用户点击窗口的关闭按钮时,将会调用func。此外还有一些协议:WM_SAVE_YOURSELF(当窗口被保存,被弃用),WM_TAKE_FOCUS(当窗口获取焦点,无效),但是都没有什么用。

下面的示例:在用户点击关闭按钮的时候,打印“你不能关闭”。

from tkinter import *
from PIL import Image, ImageTk

root = Tk()
root.protocol("WM_DELETE_WINDOW", lambda:print("你不能关闭"))

mainloop()

 

默认窗口检测到WM_DELETE_WINDOW会执行窗口的destroy方法将窗口销毁,但是更改了WM_DELETE_WINDOW的方法后,就只会执行给定的func回调函数。

resizable(width=None, height=None)

设置是否允许改变窗口尺寸。

state(newstate=None)

设置窗口的状态,newstate可以是"normal"(正常), "iconic"(最小化), "withdrawn"(被隐藏), "icon"(Wm.iconwindow), "zoomed"(最大化)。

title(string=None)

设置窗口的标题。

transient(master=None)

设置窗口为master窗口的临时窗口,临时窗口没有最大化和最小化按钮,只有关闭按钮。 可以参考Python tkinter一些十分灵活的运用方式和实用函数的第一节。

withdraw()

隐藏窗口,和最小化不同的是,隐藏的窗口不会在任务栏上显示,用户无法还原。和deiconify方法相反。

2.15 Listbox

Listbox是列表框,里面可以添加一些文本项目,在列表框中竖向显示。可以让用户选择它们。

参考资料:Python ---(七)Tkinter窗口组件:Listbox_近视的脚踏实地的博客-CSDN博客

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

参数 作用
width 组件的宽,单位是字母的平均宽度
height 组件的高,单位是项目的数量
listvariable 设置与Listbox关联的variable,是一个StringVar,不同项目用空格隔开(不推荐)。
selectmode 组件的选择模式,可以是"browse"(单选,可用鼠标拖动或方向键改变选择,默认模式), "single"(单选,只能鼠标点击改变选择), "extended"(多选,需拖动鼠标或结合Shift或Ctrl键才能多选), "multiple"(多选,点击多个选项就能多次选择)
xscrollcommand x方向滚动条(下一节介绍)
yscrollcommand y方向滚动条(下一节介绍)

常用方法: 

方法 作用
activate(index) 将位于index位置的项目激活(在下方画下划线)
bbox(index) 返回位于index位置的项目的边框尺寸信息,返回值是(xoffset, yoffset, width, height),表示左上角的偏移和宽高。
curselection() 返回被选中选项的索引的元组
delete(first, last=None) 删除first到last的选项
insert(index, *elements) 在列表框中添加单或多个选项
get(first, last=None) 如果不指定last,返回first位置的选项;如果指定last,返回两个位置之间的选项
index(index) 返回index位置的数字索引,如index("end")返回最后一个选项的数字索引
itemconfig(index, **option) 设置index位置的选项的参数,可以设置的有:bg(background), fg(foreground), selectbackground, selectforeground
itemcget(index, option) 返回index位置的选项的option参数选项值
see(index)

滚动列表框,使位于index位置的项目可见

selection_set(first, last=None) 选中first到last的项目
selection_clear(first, last=None) 取消选中first到last的项目
selection_includes(index) 返回位于index位置的项目的选中状态,1表示选中,0表示未选中
selection_anchor(index) 在index位置的项目设置锚点(类似于一个标记,可通过特殊索引"anchor"访问锚点)
size() 返回列表框中选项数量

创建Listbox

from tkinter import *

root = Tk()

lb = Listbox(root)
lb.pack()

mainloop()

 

这样就创建了一个Listbox,不过里面什么项目也没有。

虚拟事件<<ListboxSelect>>

Listbox中有项目选中时会产生一个虚拟事件<<ListboxSelect>>,可以被bind捕捉到。

from tkinter import *

root = Tk()

lb = Listbox(root)
lb.pack()

for n in range(20):
    lb.insert("end", n)

def select(event):
    print(lb.curselection()) #打印选中项的索引
    
lb.bind("<<ListboxSelect>>", select)

mainloop()

 

如图示,选中项目时会打印选中的项目索引。

see方法

see方法可以滚动列表框,使位于index位置的项目可见。

from tkinter import *

root = Tk()

lb = Listbox(root)
lb.pack()

for n in range(20):
    lb.insert("end", n)

Button(root, text="see end", command=lambda:lb.see("end")).pack()

mainloop()

 点击按钮>>>

点击按钮后列表框滚动到了end位置。

实例:列表编辑器

下面是一个实例,用户可以添加或删除列表框中的内容。

from tkinter import *

root = Tk()

def add():
    lb.insert("end", entry.get())

def remove():
    try:
        lb.delete(lb.curselection()[0])
    except: #如果没有选中列表框内容会报错
        pass
    
lb = Listbox(root)
lb.pack()

entry = Entry(root)
entry.pack()

Button(root, text="Add", command=add).pack()
Button(root, text="Remove", command=remove).pack()

root.mainloop()

2.16 Scrollbar

Scrollbar也就是滚动条,可以起到滚动组件,使用户能够完整看到的效果。但也有部分组件不支持滚动条。

参考资料:Python ---(八)Tkinter窗口组件:Scrollbar_近视的脚踏实地的博客-CSDN博客

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

滚动条没有常规的参数height,只有width。

参数 作用
activerelief 滚动条的滑块被激活时的relief样式
command 滚动条被滚动更新时执行的回调函数,会传递给函数几个参数,可以直接传递给需滚动组件的xview和yview方法。
elementborderwidth 滚动条和箭头的边框宽度
jump 是否当鼠标松开长按滚动条才调用command,默认为False(此参数似乎无效)。
orient 滚动条的方向,可以是"horizontal"(水平,横向), "vertical"(垂直,竖向),默认是vertical
repeatdelay 鼠标长按在滚动条上时,持续触发滚动条的准备时长,默认为300(ms)
repeatinterval 持续触发滚动条的间隔,默认为100(ms)

常用方法:

方法 作用
get() 返回滑块的位置,是一个元组,包含滑块左边或上边的位置,和滑块右边或下边的位置,都是0.0 ~ 1.0之间的浮点数,代表占整个滚动条的比例
set(*args) 设置滑块的位置,需提供两个参数,分别是滑块左边或上边的位置,和滑块右边或下边的位置,都是0.0 ~ 1.0之间的浮点数,代表占整个滚动条的比例

创建Scrollbar

from tkinter import *

root = Tk()

sb = Scrollbar(root)
sb.pack(side="right", fill="y")

mainloop()

这段代码在屏幕右侧绘制了一个滚动条。这个滚动条没有绑定任何可滚动的组件,所以没有任何用处。在映射滚动条时,通常会加入fill="y"这个参数,让滚动条完全伸展开,方便拖拽(在水平滚动条中是fill="x",grid布局则要指定sticky)。

XView和YView类

在tkinter中有XView类和YView类,所有支持滚动条的组件继承它们。支持x方向滚动条则继承XView,支持y方向滚动条则继承YView。比如Listbox组件同时支持x,y方向滚动条,而Entry组件只支持x方向的滚动条。

下面介绍一下XView的方法(YView的方法和XView相比,只是方法名字中的xview改为了yview)。

方法 作用
xview(*args) 在x方向滚动组件。需提供几个参数,第一个是滚动类型,可以是"moveto"(滚动到), "scroll"(向右或向下滚动)。如果滚动类型是moveto,则还需要提供一个参数表示滚动到的位置,是0.0 ~ 1.0之间的浮点数。如果滚动类型是scroll,则还需要提供滚动的数量,和滚动单位。滚动单位可以是"units"(按滚动单位滚动), "pages"(按页面滚动)。
xview_moveto(fraction) 和xview(“moveto”, fraction) 一样
xview_scroll(number, what) 和xview("scroll", number, what)一样

支持滚动条的组件,本身有xscrollcommand和yscrollcommand两个参数,可以设置为滚动条的set方法,滚动条拖拽的时候会让滚动条的位置改变。如果不设置这两个参数,那么滚动条位置拖拽后会返回原位。

同时还要设置滚动条的command参数为需滚动组件的xview或yview方法,因为command在滚动条拖拽时调用,会将滚动信息传递给command,使组件滚动。 

orient参数

orient参数指定滚动条的朝向。部分组件也有这个方法,都有两个可选值:"horizontal"(水平,横向), "vertical"(垂直,竖向)。

下面是这两个orient形态的滚动条:

horizontal
vertical

滚动条绑定组件

Listbox继承XView和YView,支持滚动条,下面就以Listbox为例示范一下滚动条的绑定。

from tkinter import *

root = Tk()

sb = Scrollbar(root)
sb.pack(side="right", fill="y")

lb = Listbox(root, yscrollcommand=sb.set)
lb.pack(side="left", fill="both")
for i in range(100):
    lb.insert("end", i)

sb.config(command=lb.yview)

mainloop()

运行效果:

2.17 Message

Message是一个比较少用的组件,功能基本可以被Label替代。Message组件可以自动换行,指定Label组件的wraplength也可以达到这个功能,不过Message可能更加简便一些。

参考资料:Python ---(十六)Tkinter窗口组件:Message_近视的脚踏实地的博客-CSDN博客

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

参数和Label基本一样,但有一个参数aspect,表示组件达到多少像素换行。

2.18 Scale

Scale也就是标尺组件。用户可以通过拖拽滑块,设定一个数值。

参考资料:Tkinter 组件详解(十):Scale_来自江南的你的博客-CSDN博客

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

参数 作用
length 设置Scale的长度
width 设置Scale的宽度
label 在Scale上显示一个文字标签
command Scale数值改变时执行的回调函数,会传递给该函数当前Scale的值
from_ 设置Scale的最小值,默认是0
to 设置Scale的最大值,默认是100
digits 刻度数值最多显示的数字位数
orient 设置Scale的朝向,可以是"horizontal"(水平)或"vertical"(垂直)
resolution 设置滑块拖动的步长(也就是拖动一次滑块,滑块移动的数值长度),默认为1
showvalue 设置是否在滑块旁边显示当前的数值
sliderlength 设置滑块的长度
sliderrelief 设置滑块的样式,默认是"raised"
tickinterval 设置显示的刻度,默认不显示
troughcolor 设置凹槽的颜色
variable 设置与Scale值相关联的variable

常用方法:

方法 作用
get() 返回Scale的值
set(value) 设置Scale的值

创建Scale

from tkinter import *

root = Tk()

scale = Scale(root)
scale.pack()

mainloop()

用户可以拖动滑块,设定滑块的值。

from_和to参数

设置这两个参数可以设定拖拽的最小和最大值。

from tkinter import *

root = Tk()

scale = Scale(root, from_=10, to=30)
scale.pack()

mainloop()

 

滑块只能从10拖动到30。

tickinterval参数

tickinterval参数使Scale可以添加刻度数值。如from_=0, to=100, tickinterval=10的Scale:

垂直的Scale的刻度显示在左边,水平的Scale则显示在下面。

label参数

label参数可以显示在Scale旁边显示一个标签。例如:label="拖动滑块":

垂直的Scale的标签在右边,水平的Scale则在显示上面。 

resolution参数

resolution参数设置Scale的步长,默认为1。如resolution=0.1, from_=0, to=100,那么你可以在0到100之间拖动滑块,每次可拖动0.1个数值。每次拖动的数值都是0.1,不能小于这个数。

实例:颜色调节器

下面是一个简单的小程序,用户可以拖拽Scale滑块控制背景的颜色。

from tkinter import *

root = Tk()

def change(x):
    color = "#%02x%02x%02x"%(r.get(),
                             g.get(),
                             b.get()) #将普通的RGB色彩元组转换成16进制的形式
    for w in root.winfo_children(): #设置Scale的背景色
        w.config(bg=color)
    
r = Scale(root, from_=0, to=255, fg="red", command=change)
r.pack(side="left")

g = Scale(root, from_=0, to=255, fg="green", command=change)
g.pack(side="left")

b = Scale(root, from_=0, to=255, fg="blue", command=change)
b.pack(side="left")

mainloop()

2.19 Spinbox

Spinbox和Entry组件很类似,可以算是Entry组件的一个变形。Spinbox拥有Entry组件的所有参数。不同的是,Spinbox的侧面多了一个上箭头和一个下箭头,可以调节Spinbox的值。当然用户也可以在里面输入

参考资料:Python ---(十七)Tkinter窗口组件:Spinbox_近视的脚踏实地的博客-CSDN博客

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

下面是Spinbox比Entry多的参数选项。

参数 作用
buttonbackground Spinbox调节箭头的背景颜色
buttoncursor 鼠标在调节箭头上方的样式
buttondownrelief 下调节箭头的relief样式
buttonuprelief 上调节箭头的relief样式
command 点击调节箭头时执行的回调函数
from_ 设置调节箭头调节的最小数值
to 设置调节箭头调节的最大数值
format 设置调节箭头调整数值的数值格式,使用%格式化,如:"%4.4f"
increment 调节箭头调节数值的步长
values 设置调节箭头可调节值的元组,和from_, to只能指定一边
wrap 可调节值是否可以循环调节,比如wrap=True, values=("0", "1", "2"),然后一直点击下箭头,那么Spinbox的值依次变成"0", "1", "2", "0", "1", "2"的循环。如果wrap=False,那么无法循环调节,调节到"2"点下箭头就无效了。默认wrap=False

常用方法同Entry。 

创建Spinbox

from tkinter import *

root = Tk()

spinbox = Spinbox(root)
spinbox.pack()

mainloop()

由于没有指定from_, to或values,所以箭头按了也无效。

from_, to和increment参数

如设置from_=0, to=10,那么点击上下箭头的时候,文本框里面的内容会在0到10之间调节。但用户仍然可以在Spinbox中输入任何内容。

increment参数指定点击箭头的步长,类似于Scale组件的resolution参数选项。

values参数

values参数和上面的from_, to, increment只能指定一边。values参数传递一个元组之类的序列。比如values=("Python", "C", "Java", "Tcl"),那么点击上下箭头的时候,文本框中的内容会在元组里面切换。

readonly状态

Spinbox可以设置为readonly状态,和Entry一样。设置为readonly的时候,文本框中不能输入,但是仍可以通过按上下箭头调节Spinbox的值。

2.20 OptionMenu

OptionMenu是选项菜单,用户可以下拉一个选择菜单,指定OptionMenu的值。

参考资料:Python ---(十五)Tkinter窗口组件:OptionMenu_近视的脚踏实地的博客-CSDN博客

OptionMenu(master, variable, value, *values, **kwargs)

这个组件比较特殊,它继承Menubutton类,有一些必选参数。比如master参数在其他的组件是可选参数,如果不指定master将会自动继承主Tk窗口。而OptionMenu必选master, variable参数。

参数 作用
master 指定父容器
variable 指定绑定的variable,设为选项菜单的值
value 选项菜单的初始选择值,没什么用,仍需要设置variable的值
*values 选项菜单的可选项(不需要再加上value,初始选择值会自动添加到可选项中)
**kwargs OptionMenu继承Menubutton类,在此处指定Menubutton的**kw选项值

创建OptionMenu

from tkinter import *

root = Tk()

var = StringVar()
var.set("Python") #设置OptionMenu的值

m = OptionMenu(root, var, "Python", "C", "Java")
m.pack()

mainloop()

此处创建了一个选项菜单,可以有3个可选项。获取OptionMenu的值,只需要执行绑定的variable的get方法。

2.21 PanedWindow

PanedWindow组件是Tk8.4新增的组件,类似于Frame。不同的是,PanedWindow组件允许用户调节子组件的布局。每个添加到PanedWindow的子组件作为一个窗格管理。

参考资料:Python ---(十八)Tkinter窗口组件:PanedWindow_近视的脚踏实地的博客-CSDN博客

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

参数 作用
showhandle 是否显示调整窗格布局的手柄,是一个正方形
orient 窗格的分布朝向,可以是"horizontal"(水平), "vertical"(垂直)
sashpad 分割线和组件的间距
sashrelief 分割线的relief样式,默认是"flat"
sashwidth 分割线的宽度
handlepad 手柄在分割线上的位置,默认是8(像素)
handlesize 手柄的边长,默认是8(像素)
opaqueresize 窗格尺寸是否随鼠标拖拽而改变,默认为True,如果设为False,只有释放鼠标窗格尺寸才会改变

 常用方法:

方法 作用
add(child, **options) 将child组件添加到PanedWindow中,option选项稍后介绍
forget(child) 从PanedWindow中移除child组件
panecget(child, option) 返回child组件option选项的值
paneconfig(child, **options) 设置child组件option选项的值
panes() 返回子组件的列表

创建PanedWindow

from tkinter import *

root = Tk()

w = PanedWindow(root, orient="horizontal")
w.pack(fill="both", expand=True)

mainloop()

这段代码创建了一个空的水平方向PanedWindow,需要在里面添加组件才能看出来。 

add方法

add方法用于在PanedWindow中添加组件。如果是水平的PanedWindow,添加的组件都按水平方向排放。如果是垂直PanedWindow,添加的组件按竖直方向排放。 

add(child, **options)

options可以是这些参数选项:

参数 作用
after 将child组件排放到after组件的后面
before 将child组件排放到before组件的前面
width 排放时child的宽度
height 排放时child的高度
minsize 窗格长度的最小值(在水平PanedWindow中是窗格的宽,垂直则是窗格的高)
padx 组件的x方向间距
pady 组件的y方向间距
sticky 组件位于窗格的位置,和grid布局的sticky参数作用一样
from tkinter import *

root = Tk()

w = PanedWindow(root, orient="horizontal")
w.pack(fill="both", expand=True)

b = Button(w, text="1b")
w.add(b)

b = Button(w, text="2b")
w.add(b)

mainloop()

代码生成了两个按钮,中间有一个细小的间隔,是窗格之间的分割线。因为分割线默认是"flat",所以是看不见的, 如可见需设置sashrelief参数。可以拖拽这个分割线,来调整窗格之间的大小。

showhandle参数

showhandle参数如果设置为True,将会在分割线的位置添加一个手柄。用户可以拖拽这个手柄,这样可以方便地调整窗格的大小。

手柄是一个正方形。

2.22 Text

Text是多行文本输入框,和Entry不同的是,Entry只有单行。并且Text里面不仅能够插入文本,还可以插入图片、组件等,还可以有标记功能,对于特殊的内容改变颜色。

参考资料:Python ---(十)Tkinter窗口组件:Text_近视的脚踏实地的博客-CSDN博客

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

Text的参数有一大部分和Entry的参数相同,如光标、激活、颜色一类的参数。

参数 作用
width Text的宽,以字符数量为单位
height Text的高,以行数为单位
undo 设置是否开启撤销功能,默认为False;开启撤销功能时,用户可以按下Ctrl+Z进行撤销操作
autoseparators 设置是否自动插入撤销分隔,默认为True
maxundo 允许撤销的数量,设置为-1代表无限次
padx 设置内容与边框的x方向间距
pady 设置内容与边框的y方向间距
wrap 设置Text的换行方式,可以是"none"(不自动换行), "char"(按字符换行), "word"(按单词换行)
xscrollcommand x方向滚动
yscrollcommand y方向滚动

常用方法:

方法 作用
bbox(index) 返回位于index字符的边界框位置(x, y, width, height),需先调用update方法
delete(start, end=None) 删除从start到end的内容
insert(index, text, *tag) 在index位置插入text,并标记为*tag
dump(index1, index2=None, command=None, **kw) 以列表形式返回Text的插入内容
get(index1, index2=None) 返回index到index2的文本内容(注:不是插入内容,Text里面不仅可以插入文本)
see(index) 滚动Text,使位于index的文本可见
edit_redo() 重做,需设置undo=True
edit_undo() 撤销,需设置undo=True
edit_reset() 清空文本操作记录
edit_separator() 插入撤销分隔
index(index) 将index的位置以line.column返回
replace(index1, index2, chars, *args) 将index1到index2的内容替换为chars字符串,*args设定tag
search(pattern, index, stopindex=None, forwards=None, backwards=None, exact=None, regexp=None, nocase=None, count=None) 在index到stopindex的文本之间搜索pattern字符串

除了这些方法外,还有一些tag, mark, image之类的方法,放在后面讲。

wrap参数

wrap参数设置Text的换行方式,可以是"none"(不自动换行), "char"(按字符换行), "word"(按单词换行)。

设置为"none"时,如果字符数量超过Text的宽,不会进行换行,Text会进行滚动,以适应光标位置。

设置为"char"时,字符数量超过Text的宽,会换到下一行。

设置为"word"时,字符同样会换行,但是换到下一行的是一个完整的单词。

创建Text

from tkinter import *

root = Tk()

text = Text(root)
text.pack()

mainloop()

上面的代码创建一个Text,可以在Text里面输入内容。 

撤销和重做

用户可以在Text中进行撤销和重做操作。开启撤销和重做操作,首先要设置undo=True,然后用户可以按Ctrl+Z来撤销。

text = Text(root, undo=True)

edit_undo和edit_redo方法用于撤销和重做,edit_undo方法执行一次撤销操作,edit_redo方法执行一次重做操作。如果没有内容可撤销或重做会报错。如下示例:

from tkinter import *

root = Tk()

text = Text(root, undo=1)
text.pack()

Button(root, text="Undo", command=text.edit_undo).pack()
Button(root, text="Redo", command=text.edit_redo).pack()

mainloop()

 

但是测试的时候,会发现:每当换行或粘贴文本的时候,才会认为这是进行了一次文本操作。撤销的时候,没能按照输入字符进行撤销。这是因为Text设置了自动加入撤销分隔,自动插入的方式和我们的期望不同。要实现按字符撤销,需要手动加入撤销分隔。

首先需要设置自动加入撤销分隔为False,也就是autoseparators=False。然后绑定<Key>,每当输入一个字符调用edit_separator()方法进行手动撤销分隔。如下示例:

from tkinter import *

root = Tk()

text = Text(root, undo=True, autoseparators=False)
text.pack()
text.bind("<Key>", lambda e: text.edit_separator())

Button(root, text="Undo", command=text.edit_undo).pack()
Button(root, text="Redo", command=text.edit_redo).pack()

mainloop()

运行后,发现成功按照字符撤销。 

索引

Text指定字符位置的索引比较特殊,下面介绍一下Text的索引。

  • 表示为line.column的格式:line是行数,column是列数,行数和列数之间用一个"."隔开,可以是一个浮点数或字符串。比如:第一行,第一个字符表示为"1.0"或1.0;第三行,第四个字符表示为"3.3"或3.3。行数的索引以1为开始,列数的索引以0为开始。
  • current:表示离鼠标上一次点击位置最近的一个字符。
  • insert:表示光标位置。
  • end:表示结尾的位置。
  • 表示为line.end的格式:line是行数,end代表结尾,是一个字符串。表示第line行的最后一个字符。比如:第二行最后一个字符表示为"2.end"。
  • 表示为mark的名称:mark下文介绍,如果写作mark的名称可以表示mark的位置。上面的current和insert是两个预定义的mark。
  • 表示为tagName.first/last:tag下文介绍,如果写作tag的名称加上.first表示tag的第一个字符之前,"tagName.last"表示tagName的最后一个字符之后。
  • sel.first/last:sel是一个特殊的tag,"sel.first"代表选中内容的开头字符之前,"sel.last"代表选中内容的结尾字符之后。
  • 表示为window或image的对象字符串:如果插入了某个组件或图像,可以表示为它们的字符串形式(执行str)来表示它们的位置。
  • 表示为@x, y:表示离(x, y)窗口位置最接近的字符。比如"@100, 100"表示最接近窗口位置(100, 100)的字符。
  • 位置+表达式字符串:可以在上述的索引后面加上一些特殊的表达式来指定位置,表达式的规范如下。
    表达式 作用 示例
    "+ %d chars"%count 索引往后移动count个字符 "1.0+ 2 chars"为"1.2"位置
    "- %d chars"%count 索引往前移动count个字符 "1.2- 2 chars"为"1.0"位置
    "+ %d lines"%count 索引向后移动count个字符 "1.0+ 2lines"为"3.0"位置
    "- %d lines"%count 索引向前移动count个字符 "3.0- 2lines"为"1.0"位置
    " linestart" 索引移动到这一行的起始处,表达式前需用空格隔开 "1.5 linestart"为"1.0"位置
    " lineend" 索引移动到这一行的末尾处,表达式前需用空格隔开 "1.5 lineend"为"1.end"位置
    " wordstart" 索引移动到这个单词(非空白字符组成的整体)的起始处,表达式前需用空格隔开 如Text内容为"python tkinter",那么"1.4 wordstart"为"1.0"位置
    " wordend" 索引移动到这个单词(非空白字符组成的整体)的末尾处,表达式前需用空格隔开 如Text内容为"python tkinter",那么"1.4 wordend"为"1.6"位置
    此外,如果不会弄混,表达式还可以进行简写。比如:"insert + 3 chars"写成"insert+3c"是没有问题的。 

如想要根据一个特殊的索引,比如"insert", "@1, 2 + 2l"来获取准确的line.column式索引,可以使用index方法。

Text.index(index)

此方法返回index的line.column形式索引。

插入文字

insert方法可以在Text中插入文字。

insert(index, text, *tag) 

在index位置插入text内容。*tag是文本的tag标记,把这一串文字标记为tag, 后面会介绍tag。

需要注意的是,insert方法只能插入文字,而delete方法不仅可以删除文字,还可以删除其他的组件或图片。

插入图片

Text可以使用image_create方法插入图片。

Text.image_create(index, cnf={}, **kw)

index是插入的索引位置,**kw参数可以是:

参数 作用
align 设置图像的对齐方式,可以是"top", "center", "bottom"或"baseline"
image 设置插入的图像,是一个PhotoImage或BitmapImage
name 图像的名称,一般不需要指定
padx 图像的x方向间距
pady 图像的y方向间距

 示例如下:

from tkinter import *

root = Tk()

image = PhotoImage(file="monster.gif")

text = Text(root)
text.pack()
text.insert("end", "插入图片")
text.image_create("end", image=image)

mainloop()

 

与图片相关的方法还有如下:

image_cget(index, option)

返回index位置的图像的option选项值

image_configure(index, cnf={}, **kw)

设置index位置的图像的选项值。

image_names()

返回嵌入Text的所有图像名称。

插入组件

window_create方法可以在Text中插入组件。

window_create(index, cnf={}, **kw)

**kw参数可以是:

参数 作用
align 设置组件的对齐方式,可以是"top"(上), "center"(中), "bottom"(下)或"baseline"(基线)
create 传递一个回调函数,函数须返回一个Text的子组件用于插入Text
window 设置插入的组件,必须是Text的子组件,window和create参数指定一个即可
stretch 当行高大于组件高度时,是否延伸组件的高,默认为False
padx 组件的x方向间距
pady 组件的y方向间距

下面两个示例,效果都是一样的。 

from tkinter import *

root = Tk()

text = Text(root)
text.pack()

b = Button(text, text="MyButton")
text.window_create("end", window=b)

mainloop()
from tkinter import *

root = Tk()

text = Text(root)
text.pack()

def create_button():
    b = Button(text, text="MyButton")
    return b

text.window_create("end", create=create_button)

mainloop()

  

Mark(标记)

在Text中,可以记录一个索引的位置,在此处做一个标记,也就是mark。mark标记的位置可以在索引中使用。有两个事先定义好的mark,即"current"和"insert",参见上文。需要注意的是:"end"并不是一个mark,而是一个比较特殊的索引。

添加一个mark,需要使用mark_set方法,这个方法不仅可以添加mark,也可以更改定义过的mark。

Text.mark_set(markName, index)

在index的位置定义一个mark,名字为markName。定义了mark后,可以在索引中使用。

from tkinter import *

root = Tk()

text = Text(root)
text.pack()

text.insert("end", "123456789")
text.mark_set("myMark", "1.1") #定义一个mark,并设置位置
text.insert("myMark", "M") #在自定义的mark处插入"M"

mainloop()

如图,"M"插入到了1.1的位置。

如果想要删除mark,可以使用mark_unset方法。

Text.mark_unset(*markNames)

你可以给定一系列的markName,删除它们。但是不能删除"current"和"insert"这两个特殊mark。

如果mark附近的文本内容改变,mark也会跟着移动。如果你不理解mark的移动方式,不妨在光标旁边的文本试一下改变它们的内容,看insert标记是如何移动的。

在mark位置插入文本的时候,mark默认会往右边移动一个字符,如果想要让mark在插入时改变移动方向,可以使用mark_gravity方法。

Text.mark_gravity(markName, direction=None)

markName指定mark的名称,direction指定mark的移动方向。默认是"right",也可以设为"left"(左),设置为None则返回direction。

还有一些关于mark的用法:

mark_names()

返回Text中所有mark的名称,包括"current"和"insert"。

mark_next(index)

返回在index位置后面的一个mark的名字,不存在返回空字符串。

mark_previous(index)

返回在index位置前面的一个mark的名字,不存在返回空字符串。

Tag(标签)

Mark是对于一个索引进行记录,而Tag是对于一段文本进行记录。并且记录的这一段文字还可以进行特殊的操作,比如更改字体,更改颜色,甚至还可以进行事件绑定。

Text有一个特殊的tag叫做sel,代表选中的内容。Text对于选中内容会进行高亮显示,就是利用了sel这个tag。上文介绍过,insert插入的内容可以直接指定tag的名称。

如要自定义一个tag,须使用tag_add方法。

Text.tag_add(tagName, index1, *args)

作用:添加一个名为tagName的tag,位置是index1+*args。*args允许你提供多个位置。比如:添加一个tag,位置是1.0-1.3, 2.0-2.3,那么可以写作tag_add("tagName", 1.0, 1.3, 2.0, 2.3);如果位置是1.0-1.3, 2.0,那么以写作tag_add("tagName", 1.0, 1.3, 2.0)。

添加完了tag,可以用tag_config方法对tag的文本进行样式更改。这些参数的值也可以用tag_cget来获取

Text.tag_config = Text.tag_configure(tagName, cnf=None, **kw)

Text.tag_cget(tagName, option)

**kw给定的参数如下,用来设置tag范围内的文本。

参数 作用
borderwidth 文本的边框的宽度
relief 文本的relief
background 文本的背景色

bgstipple

bg

使用一个位图作为背景,并使用background指定的颜色填充
foreground 文本的前景色

fgstipple

fg

使用一个位图作为前景,并使用foreground指定的颜色填充
font 文本的字体
justify 文本的对齐方式,可以是"left", "right", "center",需先指定tag为该文本行的第一个字符
offset 文本相对于基线的偏移距离,升高文本则为正数(基线:一般在文本底部的一条基准线,类似于英文四线三格的第三条线)
underline 是否添加下划线,默认为False
overstrike 是否添加删除线,默认为False
wrap 换行方式

如下示例:

from tkinter import *

root = Tk()

text = Text(root)
text.pack()

text.insert("end", "123456789")
text.tag_add("tag", "1.0", "1.4")
text.tag_config("tag", background="yellow", overstrike=True)

mainloop()

 

tag可以进行事件绑定,需通过tag_bind方法。相对地,也有用于解除绑定的tag_unbind方法。

tag_bind(tagName, sequence, func, add=None)

tag_unbind(tagName, sequence, funcid=None)

tag_bind在tagName标记的文本处绑定sequence事件,回调func。比如text.tag_bind("mytag", "<Button-1>", callback),点击一下"mytag"的tag文本即可执行callback函数。如下示例,点击tag内容会自动链接到网站。

from tkinter import *
from webbrowser import open as webopen #webbrowser.open用来启动浏览器

root = Tk()

text = Text(root)
text.pack()

text.insert("end", "进入CSDN", "link") #插入内容并设置tag为"link"
text.tag_config("link", foreground="blue", underline=1)
text.tag_bind("link", "<Button-1>", lambda x:webopen("https://www.csdn.net"))

mainloop()

如果tag的位置之间发生重合,一段文本就有可能有多个tag。tag之间有优先级,多个tag的文本选项以较优先的tag为准。但如果较优先的tag中有一部分选项没有设置,那么就设置为较低tag的选项。比如一段文本有两个tag,tag1较优先,tag2优先级较低,此时设置tag1中(foreground="red", background=None),而tag2中(foreground="red", background="yellow"),那么整个段落的颜色则为(foreground="red", background="yellow")。

tag_raise和tag_lower方法分别可以提高tag的优先级和降低tag的优先级。

Text.tag_raise(tagName, aboveThis=None)

如果不指定aboveThis,则将tagName优先级提升至最高。如果指定aboveThis,则将tagName优先级提升至名为aboveThis的tag之上。

Text.tag_lower(tagName, belowThis=None)

如果不指定belowThis,则将tagName优先级降至最低。如果指定belowThis,则将tagName优先级降至名为belowThis的tag之下。

文本删除tag可以使用tag_remove方法。

Text.tag_remove(tagName, index1, index2=None)

删除tag需要指定tag的名称,还需要指定删除的范围,从index1到index2之间,将tag删除。

此外,还有一些用于tag操作的方法:

tag_names(index=None)

返回所有tag的名称,index指定位置。

tag_ranges(tagName)

返回所有tagName标记的文本以及位置信息。

tag_nextrange(tagName, index1, index2=None)

返回index1至index2之间第一个有tagName的位置。

tag_prevrange(tagName, index1, index2=None)

tag_nextrange反过来查找,返回最后一个有tagName的位置。

get和dump方法

get方法用于返回Text的文本内容的字符串,而不能返回其他插入的组件或图片。

Text.get(index1, index2=None)

返回index1到index2两个位置之间的文本。

如果还需要返回其他插入的组件或图片,就需要使用dump方法。

Text.dump(index1, index2=None, command=None, **kw)

index1和index2是获取的范围,这个方法会返回一个列表,列表的每个项目都是一个类型的插入内容,是一个三项元组。

from tkinter import *

root = Tk()

text = Text(root)
text.pack()
text.tag_config("MyTag", background="blue")

image = PhotoImage(file="monster.gif")
window = Button(text, text="这是一个按钮组件")

text.insert("end", "这是一段普通的文字")
text.insert("end", "这是一段tag文字", "MyTag")
text.image_create("end", image=image)
text.window_create("end", window=window)

mainloop()

上面的代码运行效果如图,如果再打印出text.dump("1.0", "end")获取text的内容,得到这样的输出:

 

下面详解dump返回列表中的每个元组的项的含义。第一项表示插入内容的类型,第二项表示插入内容的信息,第三项表示的是插入内容的位置。

插入内容类型(第一项) 第一项解释 第二项解释
text 文本 表示插入的文本
tagon 标签的起始 表示tag名称
tagoff 标签的结束 表示tag名称
mark mark标记 mark的名称
image 图片 表示插入的图片对象的名称,name参数可设定
window 组件 表示插入的组件对象的名称,name参数可设定

注:由于dump返回的插入组件是组件的名称,是一个字符串,不方便直接对组件对象进行操作。如果你还记得Misc类中讲解的nametowidget方法,可以使用这个方法将组件名称转换成组件对象。

search方法

search方法用于在Text中搜索某段文本。

Text.search(pattern, index, stopindex=None, forwards=None, backwards=None, exact=None, regexp=None, nocase=None, count=None)

这个方法返回搜索到的第一段文本的第一个字符的位置。参数及作用如下:

参数 作用
pattern 需要在Text内容中搜索的文本
index 起始搜索位置
stopindex 结束搜索位置(默认为最后)
forwards 由前往后查找,默认为True
backwards 由后往前查找,和forwards可指定一个
exact 搜索与pattern完全匹配的文本,和regexp, nocase指定一个
regexp 将pattern解释为正则表达式匹配,和exact, nocase指定一个
nocase 搜索忽略大小写,和exact, regexp指定一个
count 是一个IntVar,存储搜索结果的文本字符数量

2.23 tkinter图片对象

tkinter有两种图片对象,一种是PhotoImage,用于导入*.gif, *.ppm, *.pgm格式的文件,新版tk还支持*.png;还有一种是BitmapImage,用于导入*.xbm的位图格式文件。这些图片对象都可以被传递给组件的image参数。这些图片对象都支持以下方法:

方法 作用
config(**kw) 更改图片参数设置
height() 返回图片的高
width() 返回图片的宽
type() 返回图片的类型,"photo"或"bitmap"

PhotoImage

PhotoImage(name=None, cnf={}, master=None, **kw)

name用来设定图片的名称。此外,PhotoImage支持以下关键字参数。

参数 作用
data 将图像的数据内容以字符串传递;字符串可以是二进制数据或base64编码数据(支持PNG和GIF);如同时指定了data和file参数,优先使用file指定的图片
file 指定图片文件名称
format 指定文件格式名
gamma 图像的伽马值,可以理解为亮度;默认值为1,指定的值必须大于0
height 图像的高度
width 图像的宽度
palette 指定要分配用于显示此图像的颜色立方体的分辨率,因此指定从显示它的窗口的颜色图中使用的颜色数。调色板规范字符串可以是一个十进制数,指定要使用的灰色阴影数,也可以是由斜线 (/) 分隔的三个十进制数,分别指定要使用的红色、绿色和蓝色阴影数。 如果使用第一种形式(单个数字),图像将以单色(即灰度)显示

除上描述的方法外,还支持以下方法:

方法 作用
blank() 将图片设为完全透明
cget(option) 获取option参数的值
copy() 复制图片,返回新的图片对象
zoom(x, y="") 返回原图像在x方向缩放至原来x倍,y方向缩放至原来y倍的图像;如不指定y,则y同x
subsample(x, y="") 将图片在x方向缩放至原来x分之一的大小,y方向缩放至原来y分之一的大小;如果x为负数,则图像垂直翻转;如果y为负数,则图像水平翻转;如不指定y,则y同x
get(x, y) 返回在x, y像素位置上的颜色元组(red, green, blue)
put(data, to=None) 从to位置的像素点开始向设置右方像素的颜色;data需提供[(color, color, ...), (color, color, ...), ...]这样的形式,列表中每一个项都表示一行,每一个项中间设定了这一行需改变的像素点颜色
write(filename, format=None, from_coords=None) 将图像写入filename文件,图片格式为format;from_coords指定写入的图像范围,可以是(x1, y1, x2, y2)表示一个矩形范围,或是(x1, y1)表示从一个点的位置到图片右下角,也可以不指定表示整个图像
transparency_get(x, y) 返回一个布尔值,根据位于x, y的像素点是否透明
transparency_set(x, y, boolean) 将x, y的像素点是否透明的状态设为boolean

BitmapImage

BitmapImage(name=None, cnf={}, master=None, **kw)

name用于设定图片的名称,此外还可以设置如下关键字参数:

参数 作用
data 将图像的数据内容以字符串形式传递;字符串必须遵循X11位图格式;如同时指定了data和file参数,优先使用data指定的图片
file 指定图片文件名称
background 设置位图的背景色
foreground 设置位图的前景色
maskdata 将位图掩码的数据内容以字符串形式传递
maskfile 指定位图掩码文件名称

BitmapImage不支持除上面描述的公共方法外的其他方法。 

下一篇:Python tkinter(GUI编程)模块全解(下)_Python zzy的博客-CSDN博客

如果你在开发Python tkinter程序时遇到了问题,或是有文章内容的建议,可以私信联系我,感谢支持!

本文含有隐藏内容,请 开通VIP 后查看