欢迎光临散文网 会员登陆 & 注册

Python Tk GUI系列笔记(tkinter篇(中)) 第十九章~第二十三章

2023-08-20 13:35 作者:水母山楂  | 我要投稿

〇、前言

此系列主要介绍tkinter库——Tk图形用户界面(GUI)及其相关内容,内容参考以下网站:

TkDocs:https://tkdocs.com/(前四十一章)

C语言中文网:http://c.biancheng.net/tkinter/(前三十一章)

Python tkinter(GUI编程)模块最完整教程(上/中/下):(前四十一章)

https://blog.csdn.net/qq_48979387/article/details/125706562

https://blog.csdn.net/qq_48979387/article/details/125806479

https://blog.csdn.net/qq_48979387/article/details/125768994

Python tkinter一些十分灵活的运用方式和实用函数:(第四十二章)

https://blog.csdn.net/qq_48979387/article/details/119695934

tkinter.ttk --- Tk 风格的控件:

https://docs.python.org/zh-cn/3.11/library/tkinter.ttk.html(33~41章)

Tcl/Tk文档:

https://www.tcl.tk/man/tcl8.6/TkCmd/contents.html(前四十二章)

ttkbootstrap:https://ttkbootstrap.readthedocs.io/en/latest/zh/(43~53章)

其他参考会在章节前列出

部分内容来源网络

# 操作系统为Windows 7

Python版本3.8,Tk版本8.6

# 在“属性项数据库”及以后章节使用Python版本3.10,对运行结果基本无影响

运行结果的窗口图片会缩放到80%,96 dpi

有些运行结果会使用gif动图展示,或是有额外的补充文件,需到Python tkinter result文件中的查看

# gif录制软件:ScreenToGif

# 此系列的WPS笔记会在本系列的最后一个专栏给出

颜色代表含义:

淡灰色:注释,一般前面有#

绿色:示例

橙色:补充

紫色:示例中的input用户输入内容

红色、蓝色:突出或装饰文字作用

部分内容可能不严谨或者错误,欢迎指出

# 如果Python无tkinter可参考这篇专栏cv14759634


十九、文本框控件(Text)

(1)、概念

文本框控件用于显示和编辑多行文本,允许用户以不同的样式、属性来显示和编辑文本。它可以包含纯文本或格式化文本,同时支持嵌入图片等

# 本章中“行”, “段”或“逻辑行”(logical lines)代表文本框控件中用回车换行的文本,而“行文本”或“显示行”(display lines)代表显示在文本框中一行之内的文本。例如这个注释是一段,有三行文本

(2)、演示图

 


(3)、构造方法

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

(4)、属性项

autoseparators, background, bd, bg, blockcursor, borderwidth, cursor, endline, exportselection, fg, font, foreground, height, highlightbackground, highlightcolor, highlightthickness, inactiveselectbackground, insertbackground, insertborderwidth, insertofftime, insertontime, insertunfocussed, insertwidth, maxundo, padx, pady, relief, selectbackground, selectborderwidth, selectforeground, setgrid, spacing1, spacing2, spacing3, startline, state, tabs, tabstyle, takefocus, undo, width, wrap, xscrollcommand, yscrollcommand

1.blockcursor

是一个布尔值,指定插入光标是否绘制成一个字符大小的矩形方块。默认值为False,即一条细的垂直线

# 这个矩形方块外观相当于cmd中点击Insert后的光标外观

2.inactiveselectbackground

当窗口没有焦点时选定区的颜色。如果为空则窗口没有焦点不显示选定区

# 选定区是选定文本的区域

3.insertunfocussed

指定当控件没有焦点时插入光标的样式。'none'(默认)代表不显示光标,'hollow'代表空心方块,'solid'代表实心方块

当blockcursor为False时,'hollow'与'solid'基本没区别

示例:

blockcursor为True
inactiveselectbackground为'red'失去焦点时


blockcursor为True,insertunfocussed为'hollow'失去焦点时

4.startline, endline

都是一个整数的行索引,代表底层文本数据存储的行。startline代表储存的第一行,endline代表储存的内容最后一行的之后一行。指定空字符串可以重置它们一开始代表的行

设置startline和endline可以显示文本框较大文本中的一部分

示例:

 


指定startline=5, endline=8后:

 


指定startline='', endline=''后:

 


5.wrap

指定如果处理过宽的行文本。'none'代表每行文本正好显示为一段,'char'(默认)代表过长的每行文本会在任意字符断开,'word'代表过长的每行文本会在适合的最后一个单词断开

# “一个单词”是指任何数量相邻字母、数字或下划线组成的字符串

示例:

'none':


'char':


'word':


6.spacing1

指定每行文本上方的空白间隔(段前间距)。默认值为0

7.spacing2

指定每行文本自动换行的各行之间的空白间隔。默认值为0

8.spacing3

指定每行文本下方的空白间隔(段后间距)。默认值为0

9.undo

是否启用撤销功能,默认值为False

# 实际上也是是否启用重做功能

10.maxundo

允许撤销的数量,值为-1代表无限次

11.autoseparators

指定在撤销功能启用后,是否自动插入撤销分隔符(分隔操作记录)

# 撤销/重做机制的概述见后文“撤销/重做机制”


12.tabs

设置Tab之间的停顿

默认一个Tab是八个字符

设置特定的Tab,则要将该属性项值设置为一个序列,序列中的元素是相对于控件左边缘的距离(不包括边框)

序列中的元素应是正数且是递增的

元素后面可以跟一个字符串,代表Tab后文本的对齐方式:

'left'(默认):Tab后的文本左边缘与Tab位置对齐

'right':Tab后的文本右边缘与Tab位置对齐

'center':Tab后的文本在Tab位置的中间

'numeric':Tab后的文本如果有小数点,则最右端的小数点与Tab位置对齐;如果没有小数点,最左端数字的最小位右边缘与Tab位置对齐;如果没有数字,则文本右边缘与Tab位置对齐

 

如果序列没有足够的元素则会使用最后元素的间隔和对齐方式推断后面的Tab

如果属性项没有指定或序列为空,则使用默认值

补充:使用tkinter.font模块Font类的measure方法乘以4,可以设置Tab是4个字符

13.tabstyle

指定一行中Tab停顿与该行文本中Tab的关系,可以是以下值:

'tabular':一行文本中每个Tab字符与每个Tab停顿互相关联。如果Tab字符处于Tab停顿的右边,则会插入一个空格

'wordprocessor':一行文本中每个Tab字符与右边的第一个Tab停顿相关联

示例1:

默认停顿:


tabs=('1c', '3c', '7c'):


tabs=('1c', '3c', RIGHT, '7c'): 

 three移动到Tab的左边


tabs=('1c', '3c', NUMERIC, '7c'):  

小数点移动到Tab位置


示例2:

tabstyle=('tabular'):


tabstyle=('wordprocessor'):


# 当为'tabular'时,第三组超过Tab停顿插入一个空格;当为'wordprocessor'时,第三组超过Tab停顿移到右边下一个Tab停顿

(5)、属性项的默认值及注意事项

background, bg, fg, foreground, highlightbackground, highlightcolor, insertbackground, selectbackground, selectforeground:默认值由系统指定

takefocus, xscrollcommand, yscrollcommand:默认值为空字符串

bd:默认值为1

borderwidth:默认值为1

cursor:默认值为'xterm'

exportselection:默认值为1

font:默认值为'TkFixedFont'

height:默认值为24

highlightthickness:默认值为0

insertborderwidth:默认值为0

insertofftime:默认值为300

insertontime:默认值为600

insertwidth:默认值为2

padx:默认值为1

pady:默认值为1

relief:默认值为'sunken'

selectborderwidth:默认值为0

state:默认值为'normal'

width:默认值为80

(6)、索引

使用索引指定字符在文本框中的位置

# 除非指定display,否则索引只对应当前显示的字符,不会对应被省略隐藏的字符

1.格式

"base modifier modifier modifier ..."

# 空格不是必要的

2.base

索引的开始,可以是以下形式

2.1.line.char

对应line行中的第char个字符。line从1开始,char从0开始

如果char为'end',则是line行结束处的换行符

2.2.@x,y

对应文本框X和Y坐标的字符

2.3.end

对应文本框结束的字符(最后一个换行符之后的一个字符)

# 标记mark和标签tag见后文

2.4.mark

对应标记名为mark的字符

2.5.tag.first

对应文本框控件中第一个标签为tag的字符

2.6.tag.last

对应文本框控件中最后一个标签为tag的字符

2.7.嵌入对象

对应嵌入到文本框控件中的图像或控件

3.modifier

通过modifier修饰索引,可以是以下形式

# 空格不是必要的(除了字母之间的空格),[]中代表可选,/表示多选1,modifier中的字符串可以缩写

3.1.+/- count [display/any] chars

将索引按字符向后/前移动,count指定移动的字符数

如果指定display,则被省略的字符会被跳过而不被计算在内;如果指定any,则任何字符都会被计算在内(但图像和控件不会);否则是以索引位置进行计算

# 由于历史原因,需要指定any才是按字符移动

3.2.+/- count [display/any] indices

将索引按索引位置向后/前移动,count指定移动的字符数

如果指定display,则被省略的索引会被跳过而不被计算在内;如果指定any(默认),则任何索引都会被计算在内

3.3.+/- count [display/any] lines

将索引按行向后/前移动,count指定移动的行数

如果指定display,则显示行会被计算在内;如果指定any(默认),则每个逻辑行只会被计算一次


3.4.[display] linestart

将索引调整为该行第一个索引

如果指定display,则是显示行第一个索引,否则是逻辑行第一个索引

3.5.[display] lineend

将索引调整为该行最后一个索引

如果指定display,则是显示行最后一个索引,否则是逻辑行最后一个索引

3.6.[display] wordstart

将索引调整为当前索引所在单词的第一个字符

如果指定display,则被省略的字符会被跳过而不被计算在内,否则任何字符都会被计算在内

3.7.[display] wordend

将索引调整为当前索引所在单词的最后一个文本之后的字符

如果指定display,则被省略的字符会被跳过而不被计算在内,否则任何字符都会被计算在内

示例:

文本:

01234567890123456789012345678901234567890123456789

0123456789

abc def ghij

0123456789

0123456789

0123456789

属性项:

font=('黑体', 20), width=35, height=8

结果图:

索引:  # “-->”后的是对应字符和“line.char”索引

1.2 --> '2' (1.2)

2.2 --> '2' (2.2)  # 结果图中的第二逻辑行是第三显示行

end --> '' (7.0)

1.2 + 3 any chars --> '5' (1.5)  # 可缩写为'1.2+3a c'

1.2 + 3 any line --> '2' (4.2)

1.2 + 3 display line --> 'c' (3.2)  # 第一逻辑行的第二显示行计算在内

1.0 display lineend --> '4' (1.34)

3.8 wordend --> '\n' (3.12)  # 最后一个文本之后的字符是换行符


(7)、基本方法

1.bbox(index)

返回元组(x, y, width, height)描述索引index对应字符的矩形边界

如果字符在屏幕上不可见则width, height为0

2.compare(index1, op, index2)

比较index1和index2的索引位置,返回布尔值

op——关系运算符,值是'<', '<=', '==' '>=', '>', '!='中的一个

如果index1和index2对应文本同一字符,则它们是相等的;如果index1对应的字符在index2对应的字符之前,则index1 < index2

3.delete(index1, index2=None)

删除区间[index1, index2)之间的字符。如果只给出index1,则只删除index1对应的字符;如果index1 > index2,则不会删除任何字符

4.get(index1, index2=None)

返回区间[index1, index2)之间的字符。如果只给出index1,则只返回index1对应的字符;如果index1 > index2,则不会返回任何字符

嵌入对象将被忽略,多行文本会用'\n'分隔

5.index(index)

返回index索引对应的'line.char'形式

6.insert(index, chars, *args)

在index处插入文本chars。如果提供额外参数,则第一个参数视为标签添加到chars上(如果是可迭代对象则是每个元素(字符串除外)),后面可以再加多组这样的chars-tags对

示例:

insert(1.0, 'aaaa', ['tag_a', 'tag_b'], 'bbbb', 'tag_b')意为在1.0处插入aaaabbbb,其中aaaa被添加tag_a和tag_b索引,bbbb被添加tag_b索引

7.see(index)

滚动视图使index可见

(8)、标记

· 标记是文本框中的某个浮动的位置,处于两个字符之间,它会与相邻的文本浮动

· 删除标记周围文本不会删除标记

· 实测标记名可以是任何字符串,但建议最好不要与像'end', '1.0'之类的索引重名

· 特殊标记'insert'是插入光标的位置,'current'是最接近鼠标指针的位置

1.标记重力

标记是处于两个字符之间的位置,标记重力指定当文本插入到标记位置时标记附着的字符,它的方向是'left'或'right'

2.标记相关方法

2.1.mark_gravity(markName, direction=None)

只传入markName参数则返回对应标记的重力方向

如果传入direction,则它需是'left'或'right',用于改变标记的“重力”方向

2.2.mark_set(markName, index)

如果名为markName的标记不存在,则以'right'的重力创建一个标记,并移动到index位置

如果存在,则将名为markName的标记移动到index位置

2.3.mark_unset(*markNames)

删除markNames中的所有标记

# 特殊标记'insert'和'current'不能被删除

2.4.mark_names()

返回控件中所有标记名组成的元组,包括'insert'和'current'


2.5.mark_next(index)

返回索引index后面的标记名称,实测无标记返回None

如果index是一个标记名,则是该标记的名之后的一个标记

2.6.mark_previous(index)

返回索引index前面的标记名称,实测无标记返回None

如果index是一个标记名,则是该标记的名之前的一个标记

(9)、标签

· 标签是字符串,可以包含任何字符,但最好避免是'end', '1.0'之类的名称

· 一个标签可以与任何数量的字符相关联,一个字符也可以与任何数量的标签相关联

· 标签能控制相关联字符的外观和功能

· 标签之间有一个优先顺序,拥有更高优先顺序的标签,它所对应的属性项优先应用

· 特殊标签'sel',代表当前选定区的文本

1.标签相关方法

1.1.tag_add(tagName, index1, *args)

将标签tagName与区间[index1, args中第一个位置参数)相关联,后面可以再加多组这样的位置参数。如果最后一组这样的参数不成对,则关联最后一组前面参数的单个字符

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

将标签tagName从区间[index1, index2)中删除。如果只给出index1,则只删除index1对应的单个字符

1.3.tag_delete(*tagNames)

删除tagNames中的所有标签

1.4.tag_names(index=None)

返回index对应字符关联的所有标签名组成的元组。无参数调用返回文本框控件中的所有标签(包括特殊标签'sel')

1.5.tag_configure(tagName, cnf=None, **kw)

# 别名:tag_config

与控件的configure()相似,这里是修改标签TagName的属性项

1.6.tag_cget(tagName, option)

以字符串形式返回标签的属性项option的值

1.7.tag_raise(tagName, aboveThis=None)

将标签tagName的优先顺序升到标签aboveThis的上面

省略aboveThis则将其优先顺序升到最高

1.8.tag_lower(tagName, belowThis=None)

将标签tagName的优先顺序降到标签aboveThis的下面

省略aboveThis则将其优先顺序降到最低

1.9.tag_ranges(tagName)

以元组形式返回描述tagName相关联字符的范围

元组中每两个元素描述一个范围区间[arg1, arg2)

1.10.tag_nextrange(tagName, index1, index2=None)

在区间[index1, index2)中从左向右搜索第一个标签tagName关联字符范围的初始索引,以元组形式返回此初始索引对应的范围

如果省略index2,则index2默认是文本框末尾;如果搜索无结果则返回空元组

# 范围的“初始索引”指范围区间[arg1, arg2)中的arg1

1.11.tag_prevrange(tagName, index1, index2=None)

在区间[index2, index1)中从右向左搜索第一个标签tagName关联字符范围的初始索引,以元组形式返回此初始索引对应的范围

如果省略index2,则index2默认是文本框开头;如果搜索无结果则返回空元组


示例:

文本框内容:012345678901234567890123456789

调用控件方法:

tag_add('my_tag', '1.1', '1.5', '1.8', '1.9', '1.12', '1.15')  # 将'my_tag'标签关联到后面范围

tag_config('my_tag', background='green')  # 将'my_tag'标签关联字符的背景色变为绿色

当前结果:


调用控件方法:

tag_nextrange('my_tag', '1.2', '1.13') --> ('1.8', '1.9')

tag_prevrange('my_tag', '1.13', '1.2') --> ('1.12', '1.15')

# 从'1.2'到'1.13',('1.8', '1.9')中初始索引'1.8'是第一个被包含的;从'1.13'到'1.2',('1.12', '1.15')中初始索引'1.12'是一个被包含的

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

同控件方法bind()

# 更多信息见章节“事件处理”

1.13.tag_unbind(tagName, sequence, funcid=None)

同控件方法unbind()

# 更多信息见章节“事件处理”

2.标签属性项

使用tag_config()修改标签的属性项可以改变相关联文本的外观

2.1.background

指定背景色

2.2.foreground

指定前景色

2.3.bgstipple

指定背景填充的位图,空字符串(默认值)表示实心

2.4.fgstipple

指定前景填充的位图,空字符串(默认值)表示实心

2.5.borderwidth

指定边框宽度

2.6.relief

指定边框样式

2.7.elide

是否被省略。省略的数据(字符、图像、嵌入控件)不会显示,但进一步的行为和正常数据一样

2.8.font

指定字体

2.9.justify

指定多行文本的对齐方式。值为'left'(默认值), 'center', 'right'(或它们的缩写)

# 显示行的对齐方式由第一个非省略字符的此属性值决定

2.10.lmargin1

指定首行缩进的像素

2.11.lmargin2

指定后续行缩进的像素

2.12.lmargincolor

指定缩进的背景色

2.13.rmargin

指定文本右缩进的像素

2.14.rmargincolor

指定文本右缩进的背景色

2.15.offset

指定文本的基线与所在行的基线在垂直方向上的偏移量,单位是像素。偏移量为正则是向上偏移,为负则上向下偏移

# 使用此属性可以做出上标和下标

示例:

文本内容:H2SO4 + 2NaOH = Na2SO4 + 2H2O

调用控件方法:

tag_add('subscript', '1.1', '1.2', '1.4', '1.5', '1.18', '1.19', '1.21', '1.22', '1.27', '1.28')

tag_config('subscript', offset=-5)

当前结果:


2.16.underline

指定是否绘制下划线

2.17.underlinefg

指定下划线的颜色

2.18.overstrike

指定是否绘制删除线

2.19.overstrikefg

指定删除线的颜色

2.20.selectbackground

指定选定区的背景色

2.21.selectforeground

指定选定区的前景色

2.22.wrap

2.23.spacing1

2.24.spacing2

2.25.spacing3

2.26.tabs

2.27.tabstyle

见文本框控件中的同名属性项

(10)、嵌入对象

通过以下控件方法,可以在文本框中嵌入图像、控件,图像和控件都具有属性项

1.嵌入图像

1.1.相关方法

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

在index处嵌入图像,传入键值对设置图像的属性项,返回一个唯一的标识符(用作索引)

1.1.2.image_configure(index, cnf=None, **kw)

与控件的configure()相似,这里是修改index对应图像的属性项

1.1.3.image_cget(index, option)

以字符串形式返回index对应图像的属性项option的值

1.1.4.image_names()

返回当前文本框中嵌入图像名称组成的元组

1.2.属性项

1.2.1.align

指定图像在行中的显示位置,可选择以下的值:

'top':图像顶部与行的顶部对齐

'center':图像在行内居中

'bottom':图像底部与行的底部对齐

'baseline':图像底部与行的基线对齐

示例:  # 蓝色矩形高度小于行高

 


1.2.2.image

指定图像对象

1.2.3.name

指定嵌入图像的标识符名(重复标识符会将#nn附加到后面)

1.2.4.padx

指定水平外边距(嵌入对象周围的空白区域),单位是像素

1.2.5.pady

指定垂直外边距,单位是像素

2.嵌入控件

# 注意,如果嵌入控件的堆叠顺序在文本框控件之下,则不会显示

# 注意,一个控件同时只能在一个控件中被包装,如果想要一次创建多个控件建议使用create属性项

2.1.相关方法

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

在index处嵌入控件,传入键值对设置控件的属性项,返回None

2.1.2.window_configure(index, cnf=None, **kw)

# 别名:window_config

与控件的configure()相似,这里是修改index对应控件的属性项

2.1.3.window_cget(index, option)

以字符串形式返回index对应控件的属性项option的值

2.1.4.window_names()

返回当前文本框中嵌入控件名称组成的元组

2.2.属性项

2.2.1.create

指定一个函数,函数的返回值将作为嵌入到文本框的控件

2.2.2.stretch

指定一个布尔值,表示控件是否被垂直拉伸以填充其行

# 这会使align属性被忽略。pady属性仍会起作用

2.2.3.window

指定控件对象

2.2.4.align

2.2.5.padx

2.2.6.pady

见嵌入图像中的同名属性项


(11)、撤销/重做机制与修改标志

1.撤销/重做机制

# 实测撤销/重做机制对嵌入对象无作用

文本框控件有一个无限制的撤销和重做机制,可以取消或恢复对控件内文本的编辑

下面是撤销/重做堆栈的工作方式:

· 对控件内文本的编辑动作(插入、删除)都会堆到撤销堆栈上

· 分隔符插入到编辑动作之间。分隔符可以自动插入(autoseparators为True),也可以手动插入(控件方法edit_separator())

· 撤销操作会反转所有堆到撤销/重做堆栈的编辑动作,直到达到一个分隔符或堆栈内容用完

· 撤销操作的反转操作会插入重做堆栈

· 每当有新的编辑动作记录在撤销堆栈时,重做堆栈会被清空

2.修改标志

· 通过文本框控件的修改标志可以追踪其内容变化

· 修改标志会在文本框内文本插入、删除、撤销操作、重做操作时被设置为1,表示文本内容被修改

· 修改标志可以使用edit_modified()方法查询、修改

3.相关方法

3.1.edit(*args)

文本内容编辑相关的方法,第一个参数指定模式(见下面的方法名),后面参数是对应方法的参数

# 模式还可以是'canundo'和'canredo',会返回撤销/重做堆栈是否不为空

3.2.edit_modified(arg=None)

无参数调用返回文本框控件修改标志的值。如果传入布尔值arg,则将文本框控件修改标志的值设置为arg

3.3.edit_undo()

执行一次撤销操作,当撤销堆栈为空时抛出TclError。只当undo属性为True时才起作用

3.4.edit_redo()

执行一次重做操作,当重做堆栈为空时抛出TclError。只当undo属性为True时才起作用

3.5.edit_separator()

向撤销堆栈插入一个分隔符。只当undo属性为True时才起作用

3.6.edit_reset()

清空撤销和重做堆栈

(12)、对等文本框控件(Peer text widgets)

# “对等文本框控件”为自译

1.概念

多个文本框控件,有相同的基础数据(文本、图像、标记、标签、...)但有着不同属性项,这样的文本框控件称为对等文本框控件(Peer text widgets)

2.特点

· 对等文本框控件基础数据共享,但'sel'标签、'insert'标记、'current'标记、嵌入式控件不是共享的

· 对等文本框控件可以设置不同属性项,但undo, maxundo, autoseparators除外

· 对等文本框控件通过设置startline和endline可以只显示某些行

· 对等文本框控件的“原始”文本框控件被删除后,不会影响其他对等控件


3.相关方法

3.1.peer_create(newPathName, cnf={}, **kw)

创建调用文本框控件的对等文本框控件,传入键值对设置不同的属性项

调用后,新控件的路径名称将是newPathName

newPathName必须不存在,否则抛出TclError异常

# 对等控件和“原始”控件的startline和endline属性默认相同

# 创建对等文本框控件,可以先创建一个控件,再调用它的destroy()销毁它,然后用此方法将它替换成对等文本框控件

3.2.peer_names()

返回调用文本框控件的对等文本框控件元组(不包括自己)

示例:


运行结果:

 


随便修改一个文本框内容后:

 



(13)、更多方法

1.count(index1, index2, *args)

计算并以元组形式返回index1和index2之间(不包括index2)由args给出的每个计数项的数量。如果index1在index2之后,则计数结果是负数

计数项如下:

'indices'(默认):计算所有的字符和嵌入对象

'displayindices':计算所有的非省略字符和嵌入对象

'chars':计算所有的字符

'displaychars':计算所有的非省略字符

'lines':计算所有的逻辑行,不包括index2所在的行

'displaylines':计算所有的显示行,不包括index2所在的行

'xpixels':计算index1到index2之间水平字符(不包括index2)最左边像素到最右边像素的水平像素数量

'ypixels':计算index1到index2之间垂直字符(不包括index2)最上边像素到最下边像素的水平像素数量

# 实测'xpixels'和'ypixels'需要先更新控件才能正常计数

示例:


运行结果:  # 图片没有缩放,但在插入图片时可能会模糊


2.dlineinfo(index)

返回一个五元组,该元组描述索引index所在显示行的矩形区域。前两个元素是这个矩形的左上角x和y坐标,三、四元素是该矩形的宽度和高度,第五个元素是从矩形上到下的基线位置。单位都是像素

如果索引index所有的显示上在屏幕上不可见,则返回None

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

返回区间[index1, index2)中内容组成的三元组列表。如果只给出index1,则只是index1对应内容组成的三元组列表

内容包括:文本、标记、标签、图像、控件

通过关键字参数,如果指定'all', 'image', 'mark', 'tag', 'text'或'window'中一个多个为真,则返回相应内容。没有指定则默认使用'all'

返回结果是一个三元组列表,三元组形为(key, value, index),分别是类型、值、索引。这个三元组列表是按照内容顺序的。类型tagon表示标签范围开始、类型tagoff表示标签范围结束

command——是一个函数。如果给出,则三元组列表的每个三元组都会传入三个位置参数调用该函数,且返回值变为None

示例:


运行结果:

[('tagon', 'red', '1.0'), ('text', '012', '1.0'), ('tagoff', 'red', '1.3'), ('text', '3456789', '1.3')]

[('tagon', 'red', '1.0'), ('tagoff', 'red', '1.3'), ('tagon', 'red', '2.3'), ('tagoff', 'red', '2.6'), ('tagon', 'red', '3.6'), ('tagoff', 'red', '3.9')]

在索引2.0处读取内容012,类型:text

在索引2.3处读取内容red,类型:tagon

在索引2.3处读取内容345,类型:text

在索引2.6处读取内容red,类型:tagoff

在索引2.6处读取内容6789,类型:text


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

从index开始查找符合pattern的文本,默认返回匹配文本的第一个字符的索引

指定以下参数值为True来控制查找:

forwards(默认):从index(包含)开始从左向右查找

backwards:从index(不包含)开始从右向左查找

# 由于各种原因,backwards会比forwards慢得多

exact(默认):匹配文本必须与pattern的文本相同

regexp:将pattern视为正则表达式

nocase:忽略大小写

elide:查找省略的字符

count——指定一个控制变量,将匹配文本的字符数存储到该控制变量中。指定会方法返回空字符串

stopindex——指定查找停止的索引。如果是forwards则不包含,如果是backwards则包含

5.replace(index1, index2, chars, *args)

将区间[index1, index)之间的文本替换成chars。关于args参见insert()方法

 

支持XView和YView

补充:tkinter包内模块scrolledtext

这个模块提供一个名为ScrolledText的类,这个类继承自Text类,但是多了一个y方向的滚动条

tkinter.scrolledtext.ScrolledText(master=None, **kw)

这个类的对象的frame属性是文本框控件和滚动条控件布局在其内的框架控件,vbar属性是滚动条控件


二十、画布控件(Canvas)

(1)、概念

画布控件是一个矩形区域,可以在上面绘制各种图形,也可以展示图片、文字、控件

# 下文“画布对象”指画布包含的对象,而不是画布控件本身

1.画布坐标

画布使用坐标系的方式来确定画布中的每一点

1.1.窗口坐标系

以画布控件在主窗口范围的左上角为坐标原点的坐标系

1.2.画布坐标系

以整个画布的左上角为坐标原点的坐标系

# 此章出现的坐标如果没特别说明则是画布坐标系的坐标

补充:

当画布控件scrollregion属性w与n都设置为0时,窗口坐标系(0, 0)是画布坐标系(-2, -2)

当画布控件scrollregion属性w与n都设置为2时,窗口坐标系与画布坐标系原点相同,也就是两个坐标系重合

当画布控件highlightthickness属性设置为0且scrollregion属性w与n都设置为0时,窗口坐标系(0, 0)是画布坐标系(0, 0)

2.显示列表(display list)

画布中的对象显示是有顺序的,显示列表中处于前面的对象比处于后面的对象先显示(也就是如果两个对象重叠,前面的在下面),新创建的对象会添加在显示列表的最后

可以通过方法tag_raise()和tag_lower()重新排列显示列表

显示列表中处于最前的是显示列表中最低的,处于最后的是显示列表中最高的

3.tagOrId参数

tagOrId参数指定画布上一个或多个对象

当指定值是一个整数时,会被认为是对象ID,否则会被认为是标签

tagOrId参数的值可以包含"&&"(与), "||"(或), '^'(异或), '!'(非)逻辑表达式和括号

3.1.对象ID(object ID)

画布上的对象在创建时都会分配一个唯一的ID,所有对象的ID值都是简单的整数,在画布控件的生命周期中一个对象的ID不会改变且该ID不会重复使用

3.2.标签(tag)

一个标签可以与画布上任何数量的对象相关联,一个对象也可以与任何数量的标签相关联

标签是字符串,但不可以是代表整数的字符串(例如"123")

3.2.1.标签all

这个标签与画布中每个对象相关联

3.2.2.标签current

这个标签与鼠标放在的对象相关联

(2)、演示图

(3)、构造方法

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

(4)、属性项

background, bd, bg, borderwidth, closeenough, confine, cursor, height, highlightbackground, highlightcolor, highlightthickness, insertbackground, insertborderwidth, insertofftime, insertontime, insertwidth, offset, relief, scrollregion, selectbackground, selectborderwidth, selectforeground, state, takefocus, width, xscrollcommand, xscrollincrement, yscrollcommand, yscrollincrement

# offset见后文“标准属性项”

1.closeenough

指定鼠标必须离对象多近才被认为在其中。是一个浮点数,默认值为1.0

2.scrollregion

是一个元组(w, n, e, s),定义画布可以在多大范围内滚动,w是左侧、n是顶部、e是右侧、s是底部

# 在画布控件中使用滚动条需指定该属性

3.confine

如果为True(默认值),则画布不能在scrollregion设置的范围之外滚动

4.xscrollincrement

设置画布水平滚动的“步长”。默认值为0,表示可以水平滚动到任意位置

# 例如设置20,则只能滚动到20倍数的水平位置

5.yscrollincrement

设置画布垂直滚动的“步长”。默认值为0,表示可以垂直滚动到任意位置

示例1:


运行结果:

运行时:


将滚动条拉到最右边后:

 

按几下右箭头后:


示例2:

# 区分窗口坐标系和画布坐标系

# 主窗口设置200x200,画布控件属性scrollregion设置(52, 52, 100, 100)并place(x=100, y=100)

 


上图中黄色矩形的左上角的点是窗口坐标系(0, 0),是画布坐标系(50, 50)

这个点同时向左和上平移50个像素就是窗口坐标系(-50, -50),是画布坐标系(0, 0)

下图红色是窗口坐标系、蓝色是画布坐标系:

 


(5)、属性项的默认值及注意事项

background, bg, highlightbackground, highlightcolor, insertbackground, selectbackground, selectforeground:默认值由系统指定

cursor, takefocus, xscrollcommand, yscrollcommand:默认值为空字符串

bd:默认值为0

borderwidth:默认值为0

height:默认值为'7c'

highlightthickness:默认值为2

insertborderwidth:默认值为0

insertofftime:默认值为300

insertontime:默认值为600

insertwidth:默认值为2

relief:默认值为'flat'

selectborderwidth:默认值为1

state:默认值为'normal'

width:默认值为'10c'

(6)、画布对象

使用画布控件的create_*()方法,可以在画布上绘制各种图形

画布对象也有相应的属性项,在创建时指定或使用画布控件的itemconfig()或itemconfigure()方法指定

传入的坐标都是画布坐标系的坐标

(7)、标准属性项

画布对象有一些共同的属性,这里统一说明

# 后面会在画布对象属性项编号的开头说明适用的标准属性项

1.anchor

画布对象内的锚点位置,值必须是'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'或'center'。'center'是默认值

# 锚点位置参见place()方法中的anchor

2.dash, activedash, disableddash

# 具体内容见官方文档

绘制虚线,因为在Windows只支持有限的dash patterns,所以不能设置长度和间距,只有四种虚线:

短虚线:字符'.'

长虚线:字符'-'/','/'_'

点划线:字符'.-,_'中任意两个组合

点划点线:字符'.-,_'中任意三个组合或更多组合

 

分别是在画布对象'normal', 'active', 'disabled'状态绘制

# 当鼠标在画布对象中时被认为是'active'状态,即使itemcget()获取值不是'active'

3.dashoff

在图案开始绘制前跳过的像素数

# 实测无效

4.fill , activefill, disabledfill

指定填充的颜色,空字符串表示透明。对于文本是前景色

 

分别是在画布对象'normal', 'active', 'disabled'状态填充

5.outline, activeoutline, disabledoutline

指定轮廓的颜色,空字符串表示透明

# 实测对于椭圆、矩形、弧形默认值是空字符串,其他是黑色

 

分别是在画布对象'normal', 'active', 'disabled'状态绘制

6.stipple, activestipple, disabledstipple

指定填充的位图,空字符串(默认值)表示实心。如果fill属性是空字符串则无效果

# 实测默认值是黑色

 

分别是在画布对象'normal', 'active', 'disabled'状态填充

7.outlinestipple, activeoutlinestipple, disabledoutlinestipple

指定轮廓的位图,空字符串(默认值)表示实心。如果fill属性是空字符串则无效果

 

分别是在画布对象'normal', 'active', 'disabled'状态填充

8.offset, outlineoffset

分别用于偏移填充位图和轮廓位图的点阵图案

两个属性的值形式如下:

'x,y':在画布坐标系以x和y偏移点阵图案

'#x,y':在窗口坐标系以x和y偏移点阵图案

'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw'或'center':将点阵图案中心与画布对应对应方位对齐

9.state

画布对象的状态,值是'normal', 'disabled'或'hidden'(隐藏)

10.tags

画布对象的标签,值可以是用空格分隔标签的字符串、列表(每一个元素是一个标签)、元组等

11.width, activewidth, disabledwidth

指定边框的宽度

# 不同画布对象作用不同,会具体说明

分别是在画布对象'normal', 'active', 'disabled'状态的宽度

(8)、线条

由给定坐标创建的一条或多条线段。会用线条将给定坐标按顺序相连(首末项不相连)

1.创建

create_line(*args, **kw)

create_line(x0, y0, x1, y1, ..., xn, yn, option, ...)

传入的位置参数视为坐标,传入的关键字参数视为属性项。传入序列视为坐标,传入字典键视为属性项、值视为值

返回对象ID

# 后面将不会再对此说明

2.属性项

适用的标准属性项:

dash ,activedash ,disableddash ,dashoffset ,fill ,activefill ,disabledfill ,stipple ,activestipple ,disabledstipple ,state ,tags ,width ,activewidth ,disabledwidth

2.1.width

指定线条的宽度

 

线条特定属性项:

2.2.arrow

默认线条没有箭头,值为'frist'在线条开始位置添加箭头,值为'last'在线条结束位置添加箭头,值为'both'在线条两端添加箭头

2.3.arrowshape

指定箭头的形状,值是一个三元组(d1, d2, d3),默认值是(8, 10, 3)

 

图片来源:https://tkdocs.com/shipman/create_line.html


 

# 六种样式介绍来自C语言中文网

2.4.capstyle

指定线条两端的样式,值为'butt'(默认值), 'projecting', 'round'

'butt':线段的两段平切于起点和终点

'projecting':线段的两段在起点和终点的位置将width属性设置的长度分别延长一半

'round':线段的两段在起点和终点的位置将width设置的长度分别延长一半,并以圆角进行绘制

2.5.joinstyle

指定线端连接处的样式,值为'round'(默认值), 'bevel', 'miter'

'round':以连接点为圆心,1/2width属性设置的长度为半径来绘制圆角

'bevel':在连接点处将两线段的夹角做平切操作

'miter':沿着两线段的夹角延伸至一个点

 

图片来源:https://tkdocs.com/shipman/cap-join-styles.html


2.6.smooth

默认值为False,如果为True,则绘制贝塞尔曲线替代所绘线段

2.7.splinesteps

指定多少条折线构成贝塞尔曲线,默认值是12。只能当smooth为True是才能生效


示例:

运行结果:

 


# 拉伸窗口会发现info位图的线条图案移动

(9)、椭圆

椭圆包含特殊情况的圆。椭圆位置和尺寸由左上角坐标(x0, y0)和右下角坐标(x1, y1)组成的矩形决定

1.创建

create_oval(*args, **kw)

create_oval(x0, y0, x1, y1, option, ...)

返回对象ID

2.属性项

适用的标准属性项:

dash, activedash, disableddash, dashoffset, fill, activefill, disabledfill, offset, outline, activeoutline, disabledoutline, outlineoffset, outlinestipple, activeoutlinestipple, disabledoutlinestipple, stipple, activestipple, disabledstipple, state, tags, width, activewidth, disabledwidth

2.1.width

指定轮廓的宽度

 

椭圆没有特定属性项

示例:


运行结果:

 


(10)、矩形

由左上角坐标(x0, y0)和右下角坐标(x1, y1)创建的矩形

轮廓位于矩形顶部和左侧的内部,但位于矩形底部和右侧的外部

# 也就是说如果去掉轮廓指定fill,实际填充的范围是(x0, y0)到(x1-1, y1-1)

1.创建

create_rectangle(*args, **kw)

create_rectangle(x0, y0, x1, y1, option, ...)

返回对象ID

2.属性项

适用的标准属性项:

dash, activedash, disableddash, dashoffset, fill, activefill, disabledfill, offset, outline, activeoutline, disabledoutline, outlineoffset, outlinestipple, activeoutlinestipple, disabledoutlinestipple, stipple, activestipple, disabledstipple, state, tags, width, activewidth, disabledwidth

2.1.width

指定轮廓的宽度

 

矩形没有特定属性项

(11)、多边形

用至少三个不共线的顶点依次连成的封闭图形(首末项相连)

# 实际上多边形的outline默认值为空字符串,所以如果指定该属性项,两个顶点或共线也可以显示出(线段)

1.创建

create_polygon(*args, **kw)

create_polygon(x0, y0, x1, y1, ..., option, ...)

返回对象ID

2.属性项

适用的标准属性项:

dash, activedash, disableddash, dashoffset, fill, activefill, disabledfill, offset, outline, activeoutline, disabledoutline, outlineoffset, outlinestipple, activeoutlinestipple, disabledoutlinestipple, stipple, activestipple, disabledstipple, state, tags, width, activewidth, disabledwidth

 

多边形特定属性项:

joinstyle, smooth, splinesteps:见线条中对应属性项

# 与使用线条围成的多边形区别是内部的点不认为是在线条内部

(12)、弧形

椭圆包含特殊情况的扇形、弓形、半圆形等。弧形位置和尺寸由左上角坐标(x0, y0)和右下角坐标(x1, y1)组成的矩形决定,由属性start, extent定义起始和结束角度

1.创建

create_arc(*args, **kw)

create_arc(x0, y0, x1, y1, option, ...)

返回对象ID

2.属性项

适用的标准属性项:

dash, activedash, disableddash, dashoffset, fill, activefill, disabledfill, offset, outline, activeoutline, disabledoutline, outlineoffset, outlinestipple, activeoutlinestipple, disabledoutlinestipple, stipple, activestipple, disabledstipple, state, tags, width, activewidth, disabledwidth

2.1.width

指定轮廓的宽度

 

弧形特定属性项:

2.2.start

指定起始角度,圆心所在的x轴正半轴为0.0度,默认值0.0度

值为正数表示向逆时针转动起始角度,负数表示向顺时针转动起始角度

2.3.extent

指定结束角度,弧线从start属性指定的起始角度转动,默认值90.0度

值为正数表示向逆时针转动,负数表示向顺时针转动

# 以上值如果>=360或<=-360会模360,所有指定start或extent值360相当于值为0.0

2.4.style

指定绘制的样式,值为'pieslice'(扇形,默认值), 'chord'(弓形), 'arc'(弧形)


 

图片来源:https://tkdocs.com/shipman/create_arc.html


示例:


运行结果:

 


(13)、文本

由坐标(x, y)定义文本的锚点坐标,text属性定义文本内容

1.创建

create_text(*args, **kw)

create_text(x, y, option, ...)

返回对象ID

2.属性项

适用的标准属性项:

anchor, fill, activefill, disabledfill, stipple, activestipple, disabledstipple, state, tags

2.1.fill

指定文本的前景色

 

文本特定属性项:

font, justify, text, underline:见本文档相应控件属性,其中justify默认值为'left'

2.2.width

见Label控件中的wraplength属性

2.3.angle

文本以锚点为旋转中心逆时针转动的度数

(14)、位图

由坐标(x, y)定义位图的锚点坐标,bitmap属性定义显示的位图

1.创建

create_bitmap(*args, **kw)

create_bitmap(x, y, option, ...)

返回对象ID

2.属性项

适用的标准属性项:

anchor, state, tags

 

位图特定属性项:

2.1.bitmap, activebitmap, disabledbitmap

指定显示的位图

 

分别是在画布对象'normal', 'active', 'disabled'状态

2.2.background, activebackground, disabledbackground

指定位图中比特位为0的颜色,空字符串表示透明

 

分别是在画布对象'normal', 'active', 'disabled'状态

2.3.foreground, activeforeground, disabledforeground

指定位图中比特位为1的颜色,空字符串表示透明

 

分别是在画布对象'normal', 'active', 'disabled'状态

(15)、图片

由坐标(x, y)定义图片的锚点坐标,bitmap属性定义显示的图片

1.创建

create_image(*args, **kw)

create_image(x, y, option, ...)

返回对象ID

2.属性项

适用的标准属性项:

anchor, state, tags

 

图片特定属性项:

2.1.image, activeimage, disabledimage

指定显示的图片

 

分别是在画布对象'normal', 'active', 'disabled'状态

(16)、控件

由坐标(x, y)定义控件的锚点坐标,window属性定义显示的控件

注意控件总是遮住与它重叠的任何图形,所以不能在控件上绘制其他图形。另外注意控件不会被包含其的画布边框剪切显示(除非父控件是画布),而是被父控件剪切显示

# 控件是一个矩形区域

# 实测如果绘制的控件之前被pack()、grid()或place(),绘制后会取消

1.创建

create_window(*args, **kw)

create_window(x, y, option, ...)

返回对象ID

2.属性项

使用的标准属性项:

anchor, state, tags

 

控件特定属性项:

2.1.window

指定显示的控件。注意这个控件必须是画布控件的子控件或画布控件某个祖先控件的子控件

# 这里的“祖先控件”指父控件、父控件的父控件、父控件的父控件的父控件......

2.2.width, height

控件的宽度和高度,单位是像素。如果省略,表示控件设置

(17)、方法

1.关于索引

索引对应字符或坐标,索引适用于下面方法中的first、last与index参数

# 坐标是(x, y)而不是单独的x坐标或y坐标

1.1.数字

正向索引(从0开始),可以是整数或字符串

# 对于线条和多边形的索引如果数字是奇数则自动减1,也就是它们的索引是0、2、4、...

1.2.@x,y

x, y是数字,分别被视为画布的X, Y坐标(像素为单位,数字不能是'3c'等形式),索引对应字符或坐标

# X, Y坐标是窗口坐标系的坐标

对于位于文本之外的坐标,索引对应最接近该坐标点的那一行的第一个或最后一关字符

对于位于线条和多边形的坐标,索引对应最接近该坐标点的线条和多边形的坐标点

1.3.end

索引对应字符或坐标之后的一项

# 以下索引对于线条和多边形无效

1.4.insert

索引对应插入光标的下一个字符

1.5.sel.first

索引对应选中文字的第一个字符。如果没有选中文字则抛出TclError异常

1.6.sel.last

索引对应选中文字的最后一个字符。如果没有选中文字则抛出TclError异常

2.canvasx(screenx, gridspacing=None)/canvasy(screeny, gridspacing=None)

将窗口坐标系的坐标screenx/canvas转换为画布坐标系的坐标

gridspacing——画布坐标将四舍五入到该值的最近倍数

3.coords(tagOrId, x0, y0, x1, y1, ..., xn, yn)

# 实际函数定义:dchars(*args)

只传参tagOrId,则返回tagOrId中唯一一个或显示列表中第一个画布对象的坐标的元组,坐标数量取决于画布对象的类型

如果传入新的坐标,则以这个新的坐标移动画布对象

4.dchars(tagOrId, first=0, last=first)

# 实际函数定义:dchars(*args)

删除tagOrId中每个画布对象闭区间[first, last]的字符或坐标,对于不支持索引操作的画布对象会忽略该操作

5.index(tagOrId, index)

# 实际函数定义:index(*args)

返回在tagOrId中唯一一个或显示列表中第一个适用的画布对象的index对应的数字索引

6.insert(tagOrId, index, string)

# 实际函数定义:insert(*args)

将string插入tagOrId每个画布对象对应index处

当string是有效的坐标序列(包括用空格分隔x, y对的字符串、列表、元组等)时,才会将string代表的坐标序列插入线条和多边形画布对象

7.delete(*tagOrId)

删除tagOrId中一个或多个画布对象。tagOrId不存在不会抛出异常

示例:


运行结果:

[50.0, 50.0, 100.0, 100.0]

运行时:


点击两次“延长线条”后:


 

点击“删除所有画布对象”后:


 

8.icursor(tagOrId, index)

# 实际函数定义:icursor(*args)

将tagOrId中的画布对象的插入光标设置为index。对于不支持插入光标的画布对象没有影响

# 插入光标只在画布对象有焦点时才会被显示

9.focus(tagOrId=None)

# 实际函数定义:focus(*args)

将焦点移到tagOrId中唯一一个或显示列表中第一个适用的画布对象。

如果tagOrId中没有支持插入光标的画布对象,则焦点不会被改变

如果tagOrId是空字符串,则焦点将被重置

如果tagOrId没有被指定,则返回当前拥有焦点的画布对象的ID,如果没有画布对象焦点则返回空字符串

10.type(tagOrId)

返回tagOrId中唯一一个或显示列表中第一个画布对象的类型

返回值将是'arc', 'bitmap', 'image', 'line', 'oval', 'polygon', 'rectangle', 'text'或'window'中的一个字符串

11.itemcget(tagOrId, option)

以字符串形式返回tagOrId中唯一一个或显示列表中第一个画布对象的属性项option的值

12.itemconfigure(tagOrId, cnf=None, **kw)

# 别名:itemconfig

与控件的configure()相似,这里是修改tagOrId中唯一一个或显示列表中第一个画布对象的属性项


13.move(tagOrId, xAmount, yAmount)

# 实际函数定义:move(*args)

移动tagOrId中一个或多个画布对象,将xAmount添加到它们的x坐标,将yAmount添加到它们的y坐标

14.moveto(tagOrId, x='', y='')

移动tagOrId中一个或多个画布对象到(x, y)。tagOrId中一个或显示列表的第一个画布对象的边界框(矩形区域)的左上角移动到(x, y),其他坐标(包括所有tagOrId中的画布对象)都移动到这个画布对象的相应位置

15.scale(tagOrId, xOffset, yOffset, xScale, yScale)

# 实际函数定义:scale(*args)

缩放tagOrId中一个或多个画布对象。其中,缩放的原点是(xOffset, yOffset),xScale和yScale分别确定了x坐标和y坐标的缩放系数(1.0意味着坐标没有变化)

有些画布对象只有一对坐标,使用该方法只会使它们移动

# 将画布对象的每个坐标点移动,移动后与缩放原点的x和y距离分别乘以xScale和yScale。类似于位似

示例:


运行结果:

运行时:

按下第二个按钮几次后,会发现整个图形向右下移动一个像素。然后按下第三个按钮,图形会还原

按下第一个按钮后:

# 这时再按下第三个按钮,三角形的边界框左上角会移动到(10, 10),线条坐标与三角坐标对应着改变

16.postscript(cnf={}, **kw)

将部分或全部画布内容封装成PostScript语言

# PostScript语言是一种页面描述语言,这里不过多介绍

以下是部分属性项:

16.1.colormode

指定颜色输出模式

'color'是彩色输出;'gray'是灰度输出;'mono'是黑白输出

16.2.file

如果被选定,则将PostScript写入到file的文件中,否则将以字符串形式返回PostScript

16.3.rotate

如果值为False(默认值),页面将为纵向,否则将为横向(逆时针旋转90°)

16.4.x, y

打印区域最左边和最上面的画布坐标

16.5.width, height

打印区域的宽度和高度。默认是画布的可见宽度和高度


17.dtag(tagOrId, tagToDelete)

# 实际函数定义:dtag(*args)

删除tagOrId指定的一个或多个画布对象的标签tagToDelete

18.gettags(*args)

返回tagOrId指定的一个或显示列表的第一个画布对象的所有标签,返回值是一个元组

19.addtag(*args)

将标签newtag添加到画布对象,第一个参数指定模式(见下面的方法名),后面参数是对应方法的参数

20.addtag_withtag(newtag, tagOrId)

将标签newtag添加到tagOrId指定的一个或多个画布对象

21.addtag_all(newtag)

将标签newtag添加到画布上的所有画布对象

22.addtag_above(newtag, tagOrId)

将标签newtag添加到在显示列表中tagOrId指定的一个或显示列表的最后一个画布对象之后的画布对象(之后画布对象位于tagOrId中画布对象的上方)

23.addtag_below(newtag, tagOrId)

将标签newtag添加到在显示列表中tagOrId指定的一个或显示列表的第一个画布对象之前的画布对象(之前画布对象位于tagOrId中画布对象的下方)

24.addtag_closest(newtag, x, y, halo=None, start=None)

将标签newtag添加到离(x, y)最近的画布对象(如果重叠则选择最上面的)

halo——指定增加点的有效尺寸

# 例如值为5则离点(x, y)5个像素内的画布对象视为重叠

start——值为tagOrId,将会在重叠选择时,优先选择处于tagOrId中一个或显示列表第一个画布对象下方的画布对象,如果下方的画布对象不在重叠的画布对象中则再从显示列表最后向最前选择

25.addtag_enclosed(newtag, x1, y1, x2, y2)

将标签newtag添加到完全在矩形内的所有画布对象,(x1, y1)和(x2, y2)分别是矩形左上角和右上角

26.addtag_overlapping(newtag, x1, y1, x2, y2)

将标签newtag添加到矩形内的画布对象(画布对象有一点在矩形内就被选中),(x1, y1)和(x2, y2)分别是矩形左上角和右上角

示例:


运行结果:

id1: ('a', 'b', 'd', 'i')

id2: ('b', 'i')

id3: ('b', 'c', 'g', 'i')

id4: ('b', 'e', 'i')

id5: ('b', 'f', 'i')

 


27.tag_lower(tagOrId, belowThis)

# 实际函数定义:tag_lower(*args)或tag_lower(__first, __second)

# 别名:lower

将tagOrId指定的一个或多个画布对象在显示列表中的位置移动到belowThis之前(在belowThis的下方)

belowThis——是一个标签或ID,如果包括一个以上的画布对象则是显示列表中第一个

28.tag_raise(tagOrId, aboveThis)

# 实际函数定义:tag_raise(*args)或tag_raise(__first, __second)

# 别名:tkraise

将tagOrId指定的一个或多个画布对象在显示列表中的位置移动到aboveThis之后(在aboveThis的上方)

aboveThis——是一个标签或ID,如果包括一个以上的画布对象则是显示列表中最后一个

29.tag_bind(tagOrId, sequence=None, func=None, add=None)

同控件方法bind()。标签可指定多个画布对象

注意使用标签进行绑定,在标签移除后绑定还将继续存在于画布对象,在新的画布对象添加标签也不会使绑定应用到新的画布对象上

# 更多信息见章节“事件处理”

30.tag_unbind(tagOrId, sequence, funcid=None)

同控件方法unbind()。标签可指定多个画布对象

# 更多信息见章节“事件处理”


31.create_arc(*args, **kw)

32.create_bitmap(*args, **kw)

33.create_image(*args, **kw)

34.create_line(*args, **kw)

35.create_oval(*args, **kw)

36.create_polygon(*args, **kw)

37.create_rectangle(*args, **kw)

38.create_text(*args, **kw)

39.create_window(*args, **kw)

见前文相应内容

40.find(*args)

返回画布对象ID组成的元组,如果有多个画布对象按显示列表顺序排序。第一个参数指定模式(见下面的方法名),后面参数是对应方法的参数

41.find_above(tagOrId)

42.find_all()

43.find_below(tagOrId)

44.find_closest(x, y, halo=None, start=None)

45.find_enclosed(x1, y1, x2, y2)

46.find_overlapping(x1, y1, x2, y2)

47.find_withtag(tagOrId)

参考addtag_*()中的对应方法

48.scan_mark(x, y)

49.scan_dragto(x, y, gain=10)

见章节“拖拽与缩放功能”

 

# 以下方法中tagOrId参数需要是文本类型的画布对象或是显示列表中第一个文本类型的画布对象,否则会抛出TclError异常

# 实测一个画布控件中同时只能有一个画布对象有选定区

50.select_item()

返回包含当前选定区的画布对象ID,没有则返回None

51.select_adjust(tagOrId, index)

52.select_clear()

53.select_from(tagOrId, index)

54.select_to(tagOrId, index)

见输入控件的对应方法

 

55.bbox(*args)

返回元组(x1, y1, x2, y2)描述传入画布对象id(或tag)的矩形边界

该坐标的坐标系是以画布坐标系分别向上和左两像素为原点的坐标系

 

支持XView和YView


二十一、事件处理

(1)、定义

1.事件(event)

事件是发生在应用程序上的事情

# 例如用户点击或拖动鼠标,用户输入文本及窗口管理器触发的重绘事件

2.事件处理(event handler)

事件处理是一个函数,当一个事件触发时被调用(回调函数)

3.绑定(binding)

绑定是为一个控件设置了事件处理

(2)、绑定等级(Levels of binding)

可以为三个级别设置事件处理

1.实例级

可以将一个事件绑定到一个特定的控件上

使用控件的bind()方法绑定,使用unbind()方法解绑

2.类级

可以将一个事件绑定到一个类的所有控件上

使用控件的bind_class()方法绑定,使用unbind_class()方法解绑

3.应用程序级

可以将一个事件绑定到一个应用程序的所有控件上

使用控件的bind_all()方法绑定,使用unbind_all()方法解绑

补充:三个绑定等级中的事件处理是相互独立的

(3)、事件序列/事件类型/序列码(Event sequences)

事件序列可以准确地定义事件

一般事件序列是一个包含一个或多个事件模式(event patterns),事件模式之间可以留空格,当事件模式按顺序执行后就会触发事件,事件模式有以下三种形式

# 三种形式可以混合使用,例如'a <Button-1> b'事件序列会在顺序按下a、鼠标左键、b触发

1.形式1

一个单一的ASCII字符,如a或2(区分大小写),但不能是空格字符或字符'<'

该形式代表对应字符的被按下的事件

2.形式2

<[modifier-]...type[-detail]>

整个事件模式被包含在尖括号<>内,修饰符、事件类型、描述用减号-隔开

modifier——在事件类型前面可添加一个或多个修饰符用来描述组合键

# 例如双击、按下Alt键等

type——表示事件的类型

detail——表示具体的按键或鼠标按钮

# 修饰符、事件类型、描述见后文

3.形式3

<<name>>

指定一个用户定义并命名的虚拟事件

# 虚拟事件见后文


(4)、绑定事件的控件方法

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

为控件绑定一个事件,当事件触发时执行回调函数func

sequence——事件序列

add——如果事件序列的事件已经被绑定,则该参数指定func是否附加到上一个函数之后。如果为True或'+'则附加,如果为False(默认值)或None则将替换原有的所有函数

无参数调用返回当前控件所绑定的事件元组

只传入sequence调用则返回对应事件的绑定脚本

否则返回一个标识符,用于在unbind()使用

2.unbind(sequence, funcid=None)

为控件解绑事件序列sequence定义的事件

funcid——值应是绑定事件时返回的标识符,如果传入,则只会删除事件中标识符对应的回调函数,否则删除事件中的所有回调函数

3.bind_class(className, sequence=None, func=None, add=None)

4.unbind_class(className, sequence)

分别类似于bind()和unbind()方法,区别是为className类的所有控件绑定或解绑事件

# 使用控件的winfo_class()方法获取类名

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

6.unbind_all(sequence, funcid=None)

分别类似于bind()和unbind()方法,区别是为应用程序的所有控件绑定或解绑事件

7.bindtags(tagList=None)

当为控件绑定事件时,控件会与一个特定的窗口、一个类名、关键字all或任何其他字符串相关联。这些字符串统称为绑定标签

每个控件包含一个绑定标签的列表,当控件发生事件时,会依次被应用到每个标签

默认情况每个控件有4个标签:控件名、控件类名、控件最近的顶层窗口名,关键字all

# 顶层窗口因为控件名和顶层窗口名重复,它们只有3个标签

无参数调用则以元组形式返回控件的绑定标签的列表

传参标签列表tagList会将控件的标签列表改变为tagList。如果tagList是空列表,则标签恢复到默认状态

补充:事件触发回调函数func时会传入参数Event类的对象(具体见后)

补充:如果bind()中func参数传入的是任意字符串,这会使控件原来绑定的事件失去作用。可以使用unbind()取消

(5)、事件类型和描述

1.Activate, Deactivate

分别在顶层窗口从非活动状态变为活动状态和活动状态变为非活动状态时会触发事件

# 实测用pywin32模块设置活动窗口但从没有触发过(可能是方法不对)

2.ButtonPress(缩写Button), ButtonRelease

分别在用户按下和释放鼠标按钮时触发事件

描述——1为鼠标左键;2为鼠标中键;3为鼠标右键。对于Linux还支持4和5,分别是鼠标滚轮向上和向下滚动

# 如果没有设置描述则按下或释放鼠标任何按钮都会触发事件

# 如果描述是1, 2, 3, 4或5,则事件类型可以省略,这样的形式事件类型默认是ButtonPress。例如<2>等价于<ButtonPress-2>或<Button-2>

3.Motion

在用户在控件内移动光标时触发事件

4.MouseWheel

在用户滚动鼠标滚轮时触发事件

# 这在Windows和MacOS上有效,但在Linux上无效

5.KeyPress(缩写Key), KeyRelease

分别在用户按下或释放按键时触发事件

描述——描述是具体的按键名,下面有一些例子

# 全部按键及keysym_num见https://tcl.tk/man/tcl8.6/TkCmd/keysyms.htm

[a-z][A-Z][0-9]及标点符号:相应的按键。注意数字和标点符号也包括小键盘

# 标点符号实际有对应的表示(keysym),例如"的表示是quotedbl

F[1-36]:相应的F*按键

Shift_L/Shift_R:左边和右边的Shift按键

Control_L/Control_R:左边和右边的Control按键

Alt_L/Alt_R:左边和右边的Alt按键

Up/Down/Left/Right:上/下/左/右箭头按键

Escape:Esc按键

Tab:Tab按键

Caps_Lock:Caps Lock(大写字母锁定)按键

space:space(空格)按键

BackSpace:BackSpace(退格)按键

Return:Enter(回车)按键

Insert/Delete/Home/End:相应功能按键

Prior/Next:Page Up按键和Page Down按键

Scroll_Lock:Scroll Lock(滚动锁定)按键

Pause:Pause按键

Num_Lock:Num_Lock(数字锁定)按键

less, greater:'<'和'>'按键

# 实测KP_*的按键无效果)

# 如果描述是1-5, '<', '>'和空格之外的单个字符或keysym,则事件类型可以省略,这样的形式事件类型默认是KeyPress。例如<">等价于<KeyPress-">或<Key-">

# 实测如果焦点不在绑定事件的控件上,则不会触发该事件

6.Enter, Leave

分别在用户将光标移动到和移出控件内时触发事件

# 实测对控件的子控件也有效果

7.Map, Unmap

分别在控件被映射(可见)和取消映射(不可见)时触发按键

8.FocusIn, FocusOut

分别在控件获得焦点和失去焦点时触发事件

9.Configure

在控件大小、位置或边框宽度改变时触发事件

10.Destroy

在控件被销毁时触发事件

11.Expose

在窗口全部或部分被重新绘制时触发事件

12.Visibility

在控件在屏幕上重新可见时触发

# 例如在控件包装时、窗口由最小化重新显示时。窗口最大化和取消最大化时实测也会触发

示例:


运行结果:

函数标识符: 4693952<lambda>

按钮控件绑定事件:()

按钮控件类绑定事件:('<ButtonRelease-1>', '<Button-1>', '<Leave>', '<Enter>', '<<Invoke>>', '<Key-space>')

运行时:


按下标签控件时:


输入rootquit再按回车后:

运行结束

(6)、修饰符

1.Control

当用户按住Control键

2.Alt

当用户按住Alt键

3.Shift

当用户按住Shift键

4.Lock

当用户处于大写锁定状态

5.Buttonk/Bk(k为1~5)

当用户按住相应鼠标按键(k见事件类型ButtonPress的描述)

6.Double, Triple, Quadruple

当用户连续触发2/3/4次事件

# 与连续两个事件序列不同,连续触发需要时间接近,且中间没有大量的鼠标移动。例如<Button-1><Button-1>没有时间和空间的要求

7.Metak/Mk(k为1~5或空)

当用户按住键盘上相应的Meta键

# 不同系统键盘Meta键不同

8.Extended

当用户按住“扩展键盘”上的按键

(7)、事件处理:Event对象

在事件触发时,会传递一个描述发生什么事件的Event类的对象,可以为这个对象编写对应的处理程序(函数或方法)

1.Event对象的属性

一些属性总被设置,一些属性只针对特定事件类型被设置

1.1..char

如果事件与一个ASCII字符的键按下或释放有关,则会设置该属性为该字符

1.2..delta

针对MouseWheel事件,属性值是一个整数,正数代表向上滚动,负数代表向下滚动

在Windows下,属性值是120的倍数;在MacOS下,属性值是1的倍数

1.3..width, .height

针对Configure事件,属性值是控件的新宽度/新高度,单位是像素

1.4..keycode

针对KeyPress或KeyRelease事件,属性值是一个数字代码用于识别按键

# 实测大小写字符的keycode相同,小键盘数字和顶部数字keycode不同

1.5..keysym

针对KeyPress或KeyRelease事件,属性值是按键对应的字符串名

1.6..keysym_num

针对KeyPress或KeyRelease事件,属性值是按键的数字形式。对应常规单个按键是它对应的ASCII码的整数值

# 全部按键的keysym_num见https://tcl.tk/man/tcl8.6/TkCmd/keysyms.htm

1.7..num

针对ButtonPress或ButtonRelease事件,属性值是对应的鼠标按键

1.8..serial

整数形式的序列号,会在服务器处理客户请求时增长。值越小代表事件发生越早

# 实测一些事件多次触发serial可能不变,但不会减少

1.9..state

一个描述modifier状态的整数

1.10..time

一个每毫秒都会递增的属性值,可以使用该属性确定两次事件之间的时间长度

1.11..type

一个描述事件类型的数字代码

1.12..widget

引起事件的控件

1.13..x, .y

事件发生时相对于控件左上角的鼠标X坐标和Y坐标

1.14..x_root, .y_root

事件发生时相对于屏幕左上角的鼠标X坐标和Y坐标

示例:

运行结果:

鼠标在画布上移动时:

(8)、虚拟事件

可以创建自己的新类型的事件——虚拟事件

虚拟事件可以是任何名称,它被<<...>>括起来

使用下列控件方法创建和管理虚拟事件

1.event_add(virtual, *sequences)

创建一个虚拟事件。如果虚拟事件已存在则将追加事件序列

virtual——虚拟事件的名称,是被<<...>>括起来的字符串

sequences——一个或多个事件序列。当任何一个事件序列触发时会触发虚拟事件

2.event_delete(virtual, *sequences)

删除虚拟事件virtual的事件序列sequences。如果sequences没给出则删除所有事件序列

3.event_generate(sequence, **kw)

触发事件序列sequence描述的事件

kw——通过键值对指定事件对象相应字段的值

# 事件对象的所有字段见https://tcl.tk/man/tcl8.6/TkCmd/event.htm中EVENT FIELDS

4.event_info(virtual=None)

无参数调用返回当前定义的所有虚拟事件组成的元组

传入virtual调用返回该虚拟事件的事件序列组成的元组

补充:预定虚拟事件

Tk中有一些预定的虚拟事件

如:

<<Undo>>撤销:('<Control-Key-z>', '<Control-Lock-Key-Z>')

<<Copy>>复制:('<Control-Key-c>', '<Control-Key-Insert>', '<Control-Lock-Key-C>')

一些特定控件有一些特定的虚拟控件,例如列表框被选中时触发<<ListboxSelect>>虚拟事件

更多预定虚拟事件见https://tcl.tk/man/tcl8.6/TkCmd/event.htm

示例:


运行结果:

('<Button>', '<Key>')

按下一些按键再按按键输出:

37 17

0 20

6 19

1 1  # 按钮触发的事件


二十二、控件内视图拖拽功能

参考:https://www.jianshu.com/p/4e77be43ac60?utm_campaign=haruki

# 注意这里的拖拽不是将程序外的文件拖拽到程序内,而是在拖拽控件视图

(1)、方法

一些控件(如Entry, Listbox, Canvas)拥有scan_mark()和scan_dragto()方法,使用这些方法实现对控件的扫描和调整视图

# 以下方法是Canvas中的,不同控件中同名方法参数有区别,但功能一致

1.scan_mark(x, y)

使用该方法实现对画布的扫描,它会记录x, y坐标和画布的当前视图

该方法需要与scan_dragto()一起使用

2.scan_dragto(x, y, gain=10)

该方法会计算x, y坐标与最后一次使用scan_mark(x, y)扫描之间的差调整视图,gain指定调整视图的增值

画布视图最后会被拖拽到如下位置:

# x0, y0是上次扫描位置,x1, y1是传入参数

(x0 + gain * (x1 - x0), y0 + gain * (y1 - y0))

(2)、拖拽

使用scan_mark()和scan_dragto()方法和bind()方法可实现拖拽功能。具体是将<Button-1>事件的坐标传入scan_mark(),再将<B1-Motion>事件的坐标传入scan_dragto()

示例:


运行结果:

# 正方形可以拖拽(实际上是移动了在画布中的视图,蓝色正方形在画布内坐标始终不变)


 

补充:画布的缩放功能

使用画布的scale()方法可以实现画布的缩放功能。具体是将<MouseWheel>事件(Linux上是Button-4和Button-5)的坐标确定为缩放原点,再指定缩放系数,缩放的画布对象是'all'

因为事件的坐标是窗口坐标系,所以需要将窗口坐标系转换为画布坐标系

因为缩放后画布对象会变大(或变小),所以需要对应的调整scrollregion(使其等于bbox('all')方法返回值)

示例:


运行结果:

# 文字缩放只是位置移动


 

补充:画布对象的拖拽功能

scan_mark()和scan_dragto()方法只是对控件视图的移动,如果想要在画布中拖拽画布对象,可以使用画布的move()方法

具体操作是:

在<Button-1>事件中记录点击画布对象的x和y坐标

在<B1-Motion>事件中计算偏移的x和y坐标(移动后的x和y坐标分别减去记录的x和y坐标),并将移动后的x和y坐标覆盖记录。之后使用move()方法将画布对象移动

示例:


运行结果:

 


补充:tkinter包内模块dnd

用于实现控件拖拽移动功能。但其文档中写到这个模块是实验性的,后期会被代替


二十三、属性项数据库

# 参考:

https://tkdocs.com/shipman/option-database.html

https://tcl.tk/man/tcl8.6/TkCmd/option.htm

(1)、概念

属性项数据库(Option database)用来设置控件默认的属性项值

(2)、添加方法

1.使用控件方法option_add()直接为一类控件指定默认值

2.使用控件方法option_readfile()指定一个文件

(3)、pattern格式

在两种添加方法中都需要使用pattern格式:

由一连串由句号'.'或星号'*'的字符组成,在开头可选加一个星号'*'

pattern中大写的一串字符表示一个控件类或一个属性项名,小写的一串字符表示一个控件或一个属性项名

pattern中的最后一串字符总是表示属性项,前面几串字符表示查找的控件

pattern中两串字符之间的句号表示后一串字符是前一串字符的子控件(或属性),之间的星号表示两串字符在整个控件层级结构中关联

pattern前加星号,则pattern中的第一串字符适用整个控件层级结构;否则,pattern中的第一串字符代表主窗口的名称(或类名)

# 主窗口的名称(或类名)是在实例化Tk类传入的className参数。名称默认首字母小写,类名默认首字母大小,即使传入名称的首字母是大写/小写

# 实测属性项名不能使用缩写

(4)、在程序启动后添加属性项数据库

option_add(pattern, value, priority=None)

将pattern格式指定的属性项的默认值指定为value,添加到属性项数据库中

priority——指定优先级,可以用0到100之间的整数(一般不建议)或以下值指定:

'widgetDefault':优先级20,控件默认值。使用硬编码进控件的默认值

'startupFile':优先级40,特定应用程序的默认值

'userDefault':优先级60,用户文件的默认值,例如.Xdefaults文件

'interactive':优先级80,程序启动后设置属性项的默认值。未指定priority参数,option_add()和option_readfile()方法的默认优先级

(5)、通过指定文件添加属性项数据库

option_readfile(fileName, priority=None)

将fileName对应文件中的属性项默认值添加到属性项数据库,priority指定优先级

文件不存在或格式无效则引发TclError异常

文件格式同.Xdefaults文件:

pattern格式: 值

# 注意文件的最后一行需要为空行

示例:

在与.py文件同级目录新建文件options.txt:

*Label.background: lawn green

*Label.foreground: maroon

*Label.text: 默认文本

 

.py文件:

运行结果:

 

(6)、相同优先级属性项默认值的匹配

当同一个控件有两个或更多相同优先级的属性项数据库中的默认值可以使用,会优先选择最具体的那个,具体规则是:

· 使用句号分隔比使用星号分隔更具体,例如*Label.font比*Label*font更具体

· 引用实例比引用它的类更具体,例如假设创建一个名为my_lbl的标签控件,*my_lbl.font比*Label.font更具体

· 字符串数越多越具体,例如*Label.font比*font更具体

· 如果字符串数相同,则层级越前的越具体,例如程序名为my_tk,*my_tk*font比*Label*font更具体

# 相同pattern格式的属性项默认值,后设置的会覆盖前面设置的

(7)、更多方法

1.option_get(name, classname)

获取调用控件和类别classname下属性项数据库中与属性项name匹配的属性项默认值

# 没有找到classname的作用,实测传入任何值都对返回结果没影响

# 但发现官方介绍属性项时会有Database Name和Database Class两个名称,个人猜测应传入Database Class。(Database Class名称一般是Database Name名称首字母大写。)

2.option_clear()

删除Tkinter属性项数据库中的所有属性项

(8)、自定义名称

1.自定义名称控件

在创建控件实例时传入name参数,控件名称首字母不能大写

2.自定义名称控件类

在创建控件实例时传入class_参数(有的控件类没有),控件类名称首字母应大写

如果是通过Python类继承的方式,则只会修改控件名称的默认值

Python Tk GUI系列笔记(tkinter篇(中)) 第十九章~第二十三章的评论 (共 条)

分享到微博请遵守国家法律