鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件

绘制单行文本使用 Label 组件、多行选项使用 Listbox 组件、输入框使用 Entry 组件

显示和处理多行文本就需要使用我们的 Text 组件了。

 

Text 组件十分的强大和灵活,适用于多种任务。虽然说 Text 的主要目的是显示多行文本,但是也常常被当做简单的文本处理器、文本编辑器或者网页浏览器来使用。例如说我们的 IDLE 就是 Text 组件构成的。

目录

简单用法

插入图片和组件

插入按钮

插入图片

Indexs索引

line.column

line.end

INSERT

CURRENT

END(或"end")

user-defined marks

User-defined tags("tag.first", "tag.last")

selection(SEL_FIRST, SEL_LAST)

window coordinate("@x,y")

embedded object name(window, images)

expressions

Marks用法

例一,Marks事实上就是索引,用于表示位置:

例二,如果Marks前边的内容发生变化,那么Mark的位置也会跟着移动(说白了就是Marks会记住它后边的那货):

例三,如果Marks周围的文本被删除了,Marks任然还在(只是它后面的那货被删除了,所以它六神无主,只能初始化为"1.0"):

例四,只有mark_unset()方法可以解除对Marks的封印:

Tags用法

设置样式

设置Tag优先级

事件绑定


 

简单用法

下面来演示一下 Text 组件的用法:

from tkinter import *

root = Tk()

text = Text(root, width=30, height=2) #30的意思是30个平均字符的宽度,height设置为两行
text.pack()

text.insert(INSERT, 'I Love\n')  #INSERT表示输入光标所在的位置,初始化后的输入光标默认在左上角
text.insert(END, 'Study!')

mainloop()
#生成好的Text组件可以进行编辑(并不是只读形式的)

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第1张图片

 

插入图片和组件

Text 组件不仅支持编辑和插入文本,还支持插入图片和组件。

插入按钮

from tkinter import *

root = Tk()

text = Text(root, width=30, height=5)
text.pack()

text.insert(INSERT, 'I Love\n')
text.insert(END, 'Study!')

def show():
    print('呦西,我被点了一下')

b1 = Button(text, text='点我', command=show) #注意放入的是Text而不是root了
text.window_create(INSERT, window=b1)

mainloop()

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第2张图片

 

插入图片

from tkinter import *

root = Tk()

text = Text(root, width=50, height=40)
text.pack()

photo = PhotoImage(file="D:\LOTUS专用图像\study.gif")  #只支持GIF格式的

def show():
    text.image_create(END, image=photo)

b1 = Button(text, text='点我', command=show) #注意放入的是Text而不是root了
text.window_create(INSERT, window=b1)

mainloop()

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第3张图片

 

Indexs索引

至于想要在 Text 组件中定位,就要使用到Indexs索引了。

Indexs(索引是用来指向 Text 组件中文本的位置,跟 Python 的序列索引一样,Text 组件索引也是对应实际字符之间的位置。

 

Tkinter 提供一系列不同的索引类型:

索引类型 意思
line.column 行/列
line.end 某一行的末尾
INSERT  
CURRENT  
END  
user-defined marks  
user-defined tags("tag.first", "tag.last")  
selection(SEL_FIRST, SEL_LAST)  
window coordinate("@x,y")  
embedded object name(window, images)  
expressions  

 

line.column

由于 Text 支持多行文本,就是从一维空间变成了二维空间。因此可以用行和列定位一个位置。

那么,行列就是最基础的索引方式,他们将索引位置的行号和列号以字符串的形式表示出来(中间以"."分隔,例如"1.0"表示第一列第一行)。需要注意的是,行号以1开始,列号以0开始。你还可以使用以下语法构建索引:

"%d.%d" % (line, column)

指定超出现有文本的最后一行的行号,或超出一行中列数的列号都不会引发错误。对于这样的指定,Tkinter 解释为已有内容的末尾的下一个位置。

 

需要注意的是,使用行列的索引方式看起来像是浮点值。其实不只是像而已,你在需要指定索引的时候使用浮点值代替也是可以的:

text.insert(INSERT, 'I LOVE STUDY')
print(text.get('1.2', 1.6))  #1.2  1.6可以不加双引号

使用 index() 方法可以将所有支持的“索引”格式(上面写的那一大堆,11 个)转化为“行/列”格式的索引号

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第4张图片

 

line.end

行号加上字符串 ".end" 的格式表示为该行最后一个字符的位置

text.insert(INSERT, 'I LOVE STUDY')
print(text.get('1.2', '1.end'))  # end 为小写
#从第一行第三列到第一行最后

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第5张图片

 

INSERT

INSERT 和下面两个有点类似 C 的宏定义

INSERT (或 "insert" )

对应插入光标的位置

 

CURRENT

CURRENT (或 "current" )  --用的少

对应与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,它会直到你松开它才响应(即你松开时的位置)

 

END(或"end")

对应 Text 组件的文本缓冲区最后一个字符的下一个位置

 

user-defined marks

user-defined marks 是对 Text 组件中位置的命名。INSERT 和 CURRENT 是两个预先命名好的 marks,除此之外你可以自定义 marks

 

User-defined tags("tag.first", "tag.last")

User-defined tags 代表可以分配给 Text 组件的特殊事件绑定和风格。

你可以使用 "tag.first"(使用 tag 的文本的第一个字符之前)和 "tag.last"(使用 tag 的文本的最后一个字符之后)语法表示标签的范围。

"%s.first" % tagname
"%s.last" % tagname

如果查无此 tag,那么 Tkinter 会抛出 TclError 异常

 

selection(SEL_FIRST, SEL_LAST)

selection 是一个名为 SEL(或 "sel" )的特殊 tag,表示当前被选中的范围,你可以使用 SEL_FIRST 到 SEL_LAST 来表示这个范围,如果没有选中的内容,那么 Tkinter 会抛出 TclError 异常

 

window coordinate("@x,y")

你还可以使用窗口坐标作为索引。例如在一个事件绑定中,你可以使用以下代码找到最接近鼠标位置的字符:

"@%d,%d" % (event.x, event.y)

 

embedded object name(window, images)

embedded object name 用于指向在 Text 组件中嵌入的 window 和 image 对象。要引用一个 window,只要简单的将一个 Tkinter 组件实例作为索引即可。引用一个嵌入的 image,只需使用相应的 PhotoImage 和 BitmapImage 对象

 

expressions

expressions 用于修改任何格式的索引,用字符号的形式实现修改索引的表达式。

具体表达式实现如下:

表达式 含义
+ count chars

①将索引向前(->)移动count个字符

②可以越过换行符,但不能超过END的位置

- count chars

①将索引向后(<-)移动count个字符

②可以越过换行符,但不能超过"1.0"的位置

+ count lines

①将索引向前(->)移动count行

②索引会尽量保持与移动前在同一列上,但如果移动后的那一行字符太少,将移动到该行的末尾

- count lines

①将索引向后(<-)移动count行

②索引会尽量保持与移动前在同一列上,但如果移动后的那一行字符太少,将移动到该行的末尾

linestart

①将索引移动到当前索引所在行的起始位置

②注意,使用该表达式前边必须有一个空格隔开

lineend

①将索引移动到当前索引所在行的末尾

②注意,使用该表达式前边必须有一个空格隔开

wordstart

①将索引移动到当前索引指向的单词的开头

②单词的定义是一系列字母、数字、下划线或任何非空白字符的组合

③注意,使用该该表达式前边必须有一个空格隔开

wordend

①将索引移动到当前索引指向的单词的末尾

②单词的定义是一系列字母、数字、下划线或任何非空白字符的组合

③注意,使用该该表达式前边必须有一个空格隔开

ps.只要结果不产生歧义,关键字可以被缩写,空格也可以省略。例如:"+ 5 chars" 可以简写成 "+5c"

 

在实现中,为了确保表达式为普通字符串,你可以使用 str 或格式化操作来创建一个表达式字符串。下面例子演示了如何删除插入光标前边的一个字符:

def backspace(event):
    event.widget.delete("%s-1c" % INSERT, INSERT)

 

如果看书时发现一句美句,拿出笔和本,在本上写下这句话的位置(这是 Marks),并在书上对美句画横线(这是 tag)。

Marks用法

Marks(标记)通常是嵌入到 Text 组件文本中的不可见对象。事实上 Marks 是指定字符串间的位置,并跟随相应的字符一起移动。Marks 有 INSERT,CURRENT 和 user-defined marks(用户自定义 Marks)。其中,INSERT 和 CURRENT 是 Tkinter 预定义的特殊 Marks,他们不能被删除。

 

INSERT(或 "insert") 用于指定当前插入光标的位置,Tkinter 会在该位置绘制一个闪烁的光标(因此,并不是所有的 Marks 都不可见)

 

CURRENT(或 "current")用于指定对应与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,它会直到你松开它才响应(即你松开时的位置)

 

你还可以自定义任意数量的 Marks,Marks 的名字是由普通字符串组成,可以是除了空白字符外的任何字符(为了避免歧义,你应该起一个有意义的名字)。使用 mark_set() 方法创建和移动 Marks。

 

如果你在一个 Mark 标记的位置之前插入或删除文本,那么 Marks 会跟着一起移动。删除 Marks 你需要使用 mark.unset() 方法,删除 Marks 周围的文本并不会删除 Marks 本身

 

例一,Marks 事实上就是索引,用于表示位置:

text.insert(INSERT, 'I love study')
text.mark_set('here', '1.2') #第一行第三列做一个标记
text.insert('here', '插') #利用标记插入字符串

#原来的字符串变成'I 插love study'

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第6张图片

 

例二,如果 Marks 前边的内容发生变化,那么 Mark 的位置也会跟着移动(说白了就是Marks 会记住它后边的那货):

text.insert(INSERT, 'I love study')
text.mark_set('here', '1.2')
text.insert('here', '插')
text.insert('here', '入')

#原来的字符串变成'I 插入love study'

 

例三,如果 Marks 周围的文本被删除了,Marks 仍然还在(只是它后面的那货被删除了,所以它六神无主,只能初始化为"1.0"):

text.insert(INSERT, 'I love study')
text.mark_set('here', '1.2')
text.insert('here', '插')

text.delete('1.0', 'end')
text.insert('here', '入')

#原来的字符串变成'入'

 

例四,只有 mark_unset() 方法可以解除对 Marks 的封印:

text.insert(INSERT, 'I love study')
text.mark_set('here', '1.2')
text.insert('here', '插')

text.mark_unset('here')

text.delete('1.0', 'end')
text.insert('here', '入')

#会报TclError的错误

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第7张图片

 

默认插入内容到 Marks,是插入到它的左边(就是说插入一个字符的话,Marks 向后移动了一个字符的位置)。

 

那能不能插入到 Marks 的右侧呢(即 Marks 的位置一直不变)?其实是可以的,通过 mark_gravity() 方法就可以实现:

text.insert(INSERT, 'I love study')

text.mark_set('here', '1.2')
text.mark_gravity('here', LEFT)  #默认是RIGHT,也就是说插入一个数据,Marks默认是在这个数据的右边,即可能会(插入数据在Marks的右边时)相对插入前Marks的位置移动了一个。

text.insert('here', '插')
text.insert('here', '入')

#结果是"I 入插love study"

不难总结出,Index 索引和 Marks 标记都是主要用于定位。Marks 可以看做是特殊的 Index,是一个可以自定义名字的 Index。但是他们又不是完全相同的,比如说在默认的情况下,在 Marks 指定的位置中插入数据,Marks 的位置会自动发生改变。

 

Tags用法

Tags(标签)通常用于改变 Text 组件中内容的样式和功能。你可以修改文本的字体、尺寸和颜色。另外,Tags 还允许你将文本、嵌入的组件和图片与鼠标和键盘等事件相关联。除了 user-defined tags(用户自定义的 Tags),还有一个预定义的特殊Tags:SEL。

 

SEL (或 "sel")用于表示对应的选中内容(如果有的话)。

 

可以自定义任意数量的 Tags,Tags 的名字是由普通字符串组成,可以是除了空白字符以外的任何字符。另外,任何文本内容都支持多个 Tags 描述,任何 Tag 也可以用于描述多个不同的文本内容。

 

为指定文本添加 Tags 可以使用 tag_add() 方法:

text.insert(INSERT, 'I love study very well')
text.tag_add('tag1', '1.7', '1.12', '1.14')  #第一个参数是tag的名字,之后的参数是范围。这些参数表示的范围是'1.7'到'1.12'和一个单独的'1.14'
#光是这样只是在指定位置标注了一个tag标签,还需要对这些标签进行设置
text.tag_config('tag1', background='yellow', foreground='red')  

#字符串'I love study very well'中'study'和'e'颜色改变

设置样式

如上,使用 tag_config() 方法可以设置 Tags 的样式。下面罗列了 tag_config() 方法可以使用的选项:

选项 含义
background

①指定该Tag所描述的内容的背景颜色

②注意:bg并不是该选项的缩写,在这里bg被解释成bgstipple选项的缩写

bgstipple

①指定一个位图作为背景,并使用background选项指定的颜色填充

②只有设定了background选项,该选项才会生效

③默认的标准位图有:'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question'和'warning'

borderwidth

①指定文本框的宽度

②默认值是0

③只有设定了relief选项该选项才会生效

④注意:该选项不能使用bd缩写

fgstipple

①指定一个位图作为前景色

②默认的标准位图有:'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question'和'warning'

font ①指定该Tag所描述的内容使用的字体
foreground

①指定该Tag所描述的内容使用的前景色

②注意:fg并不是该选项的缩写,在这里fg被解释为fgstipple的缩写

justify

①控制文本的对齐方式

②默认是LEFT(左对齐),还可以选择RIGHT(右对齐)和CENTER(居中)

③注意:需要将Tag指向该行的第一个字符,该选项才能生效

Imargin1

①设置Tag指向的文本块第一行的缩进

②默认值是0

③注意:需要将Tag指向该行的第一个字符或整个文本块,该选项才能生效

Imargin2

①设置Tag指向的文本块除了第一行其他行的缩进

②默认值是0

③注意:需要将Tag指向整个文本块,该选项才能生效

offset

①设置Tag指向的文本相对于基线的偏移距离

②可以控制文本相对于基线是升高(正数值)或者降低(负数值)

③默认值是0

overstrike

①在Tag指定的文本范围画一条删除线

②默认值是False

relief

①指定Tag对应范围的文本的边框样式

②可以使用的值有:SUNKEN,RAISED,GROOVE,RIDGE或FLAT

③默认值是FLAT(没有边框)

margin

①设置Tag指向的文本块右侧的缩进

②默认值是0

spacing1

①设置Tag所描述的文本块中每一行与上方的文本间隔

②注意:自动换行不算

③默认值是0

spacing2

①设置Tag所描述的文本块中自动换行的各行间的空白间隔

②注意:换行符("\n")不算

③默认值是0

spacing3

①设置Tag所描述的文本块中每一行与下方的文本间隔

②注意:自动换行不算

③默认值是0

tabs

①定制Tag所描述的文本块中Tab按键的功能

②默认Tab被定义为8个字符的宽度

③你还可以定制多个制表位:tabs=('3c', '5c', '12c')表示前三个Tab的宽度分别为3cm,5cm,12cm,接着的Tab按照最后两个的差值计算,即:19cm,26cm,33cm

④你应该注意到,它上边'c'的含义是“厘米”而不是“字符”,还可以选择的单位有"i"(英寸),"m"(毫米),"p"(DPI,大约是'1i'等于'72p')

⑤如果是一个整型值,则单位是像素

underline

①该选项设置为True的话,则Tag所描述的范围内的文本将被画上下划线

②默认值是False

wrap

①设置当一行文本的长度超过width选项设置的宽度时,是否自动换行。

②该选项的值可以是:NONE(不自动换行),CHAR(按字符自动换行)和WORD(按单词自动换行)

 

如果你对同一个范围内的文本加上多个 Tags(会形成一个栈的形式),并且设置相同的选项,那么新建的 Tag 样式会覆盖比较旧的 Tag:

from tkinter import *

root = Tk()

text = Text(root, width=30, height=5)
text.pack()

text.insert(INSERT, 'I love study very well')
text.tag_add('tag1', '1.7', '1.12', '1.14')
text.tag_add('tag2', '1.7', '1.12', '1.14')
#注意这里是创建的顺序起决定性的作用

text.tag_config('tag2', foreground='blue')
text.tag_config('tag1', background='yellow', foreground='red')
#最后的前景色是蓝色,背景色还是黄色

mainloop()

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第8张图片

这里的前景蓝色有点不那么显眼,仔细看是蓝色的。

 

设置Tag优先级

你或许想控制 Tags 间的优先级,这可以实现么?

 

你可以使用 tag_raised() 和 tag_lower() 方法来提高和降低某个 Tag 的优先级。

from tkinter import *

root = Tk()

text = Text(root, width=30, height=5)
text.pack()

text.tag_config('tag2', foreground='blue')  #设置tag的选项时,如果没有该tag,则会新建一个
text.tag_config('tag1', background='yellow', foreground='red') #此时这个就是新建的Tag的顺序
#到这里是黄底红字的

text.tag_lower('tag1')
#到这里就成了黄底蓝字

text.insert(INSERT, 'I love study very well', ('tag2', 'tag1'))  #和这里的tag选项的顺序无关。这样Tag加入的是整个文本

mainloop()

 

事件绑定

另外 Tags 还支持事件绑定,使用的是 tag_bind() 的方法。

 

下边的例子中,我们将文本("Baidu.com")与鼠标事件进行绑定,当鼠标进入该文本段时,鼠标样式切换为 "arrow" 形态,离开文本段的时候切换回 "xterm" 形态。当触发鼠标“左键点击操作”时,使用默认浏览器打开百度首页

from tkinter import *
import webbrowser

root = Tk()

text = Text(root, width=30, height=5)
text.pack()

text.insert(INSERT, 'Baidu.com的创始人是李彦宏')

text.tag_add('link', '1.0', '1.8')
text.tag_config('link', foreground='blue', underline=True)

def show_arrow_cursor(event):
    text.config(cursor='arrow')

def show_xterm_cursor(event):
    text.config(cursor='xterm')

def click(event):
    webbrowser.open('http://www.baidu.com')

text.tag_bind('link', '', show_arrow_cursor)  #指的是当鼠标进入的时候调用show_hand_cursor函数
text.tag_bind('link', '', show_xterm_cursor)
text.tag_bind('link', '', click)

mainloop()

鱼c笔记——Python 的 GUI 编程(六):Tkinter 的 Text 组件_第9张图片

 

 

你可能感兴趣的:(#,Python学习笔记)