Text 组件用于显示文本文档,包含纯文本或格式化文本(使用不同字体,嵌入图片,显示链接,甚至是带 CSS 格式的 HTML 等)。因此,它常常也被用于作为简单的文本编辑器和网页浏览器使用。
import tkinter as tk
root = tk.Tk()
# 创建了一个宽60字符、高10行的Text控件
text = tk.Text(root,width=60,height=30)
text.pack()
# 创建一个Button,每次点击给Text尾部添加一句话
btn = tk.Button(root,text='click to add text',command=lambda :text.insert('end','hello\n'))
btn.pack()
root.mainloop()
属性 | 含义 |
---|---|
autoseparators | 1. 指定实现“撤销”操作的时候是否自动插入一个“分隔符”(用于分隔操作记录); 2. 默认值是 True |
background | 1. 设置 Text 组件的背景颜色 ;2. 注意:通过使用 Tags 可以使 Text 组件中的文本支持多种背景颜色显示(请参考上方【Tags 用法】) |
bg | 跟 background 一样 |
borderwidth | 1. 设置 Entry 的边框宽度 ;2. 默认值是 1 像素 |
bd | 跟 borderwidth 一样 |
cursor | 1. 指定当鼠标在 Text 组件上飘过的时候的鼠标样式 ;2. 默认值由系统指定 |
exportselection | 1. 指定选中的文本是否可以被复制到剪贴板 ;2. 默认值是 True ;3. 可以修改为 False 表示不允许复制文本 |
font | 1. 设置 Text 组件中文本的默认字体 ;2. 注意:通过使用 Tags 可以使 Text 组件中的文本支持多种字体显示 |
foreground | 1. 设置 Text 组件中文本的颜色 ;2. 注意:通过使用 Tags 可以使 Text 组件中的文本支持多种颜色显示 |
fg | 跟 foreground 一样 |
height | 1. 设置 Text 组件的高度; 2. 注意:单位是行数,不是像素噢 |
highlightbackground | 1. 指定当 Text 组件没有获得焦点的时候高亮边框的颜色 ;2. 默认值由系统指定 |
highlightcolor | 1. 指定当 Text 组件获得焦点的时候高亮边框的颜色 ;2. 默认值由系统指定 |
highlightthickness | 1. 指定高亮边框的宽度 ;2. 默认值是 0 |
insertbackground | 1. 设置插入光标的颜色 ;2. 默认是 BLACK(或 "black") |
insertborderwidth | 1. 设置插入光标的边框宽度 ;2. 默认值是 0 3;3.你得设置 insertwidth 选项为比较大的数值才能看出来 |
insertofftime | 1. 该选项控制光标的闪烁频率(灭); 2. 单位是毫秒 |
insertontime | 1. 该选项控制光标的闪烁频率(亮); 2. 单位是毫秒 |
insertwidth | 1. 指定光标的宽度 ;2. 默认值是 2 像素 |
maxundo | 1. 设置允许“撤销”操作的最大次数 ;2. 默认值是 0 ;3. 设置为 -1 表示不限制 |
padx | 1. 指定水平方向上的额外间距(内容和边框间) ;2. 默认值是 1 |
pady | 1. 指定垂直方向上的额外间距(内容和边框间) ;2. 默认值是 1 |
relief | 1. 指定边框样式 ;2. 默认值是 "sunken" ;3. 其他可以选择的值是 "flat","raised","groove" 和 "ridge" |
selectbackground | 1. 指定被选中文本的背景颜色 ;2. 默认值由系统指定 |
selectborderwidth | 1. 指定被选中文本的边框宽度 ;2. 默认值是 0 |
selectforeground | 1. 指定被选中文本的字体颜色 ;2. 默认值由系统指定 |
setgrid | 1. 指定一个布尔类型的值,确定是否启用网格控制 ;2. 默认值是 False |
spacing1 | 1. 指定 Text 组件的文本块中每一行与上方的空白间隔; 2. 注意:自动换行不算 ;3. 默认值是 0 |
spacing2 | 1. 指定 Text 组件的文本块中自动换行的各行间的空白间隔 ;2. 注意:换行符('\n')不算 ;3. 默认值是 0 |
spacing3 | 1. 指定 Text 组件的文本中每一行与下方的空白间隔 ;2. 注意:自动换行不算; 3. 默认值是 0 |
state | 1. 默认情况下 Text 组件响应键盘和鼠标事件("normal") ;2. 如果将该选项的值设置为 "disabled",那么上述响应就不会发生,并且你无法修改里边的内容 |
tabs | 1. 定制 Tag 所描述的文本块中 Tab 按键的功能; 2. 默认 Tab 被定义为 8 个字符的宽度 ;3.你还可以定义多个制表位:tabs=('3c', '5c', '12c') 表示前 3 个 Tab 宽度分别为 3厘米,5厘米,12厘米,接着的 Tab 按照最后两个的差值计算,即:19厘米,26厘米,33厘米;4.你应该注意到了,它上边 'c' 的含义是“厘米”而不是“字符”,还可以选择的单位有 'i'(英寸),'m'(毫米)和 'p'(DPI,大约是 '1i' 等于 '72p');5.如果是一个整型值,则单位是像素 |
takefocus | 1. 指定使用 Tab 键可以将焦点移动到 Text 组件中 ;2. 默认是开启的,可以将该选项设置为 False 避免焦点在此 Text 组件中 |
undo | 1. 该选项设置为 True 开启“撤销”功能 ;2. 该选项设置为 False 关闭“撤销”功能 ;3. 默认值是 False |
width | 1. 设置 Text 组件的宽度 ;2. 注意:单位是字符数,因此 Text 组件的实际宽度还取决于字体的大小 |
wrap | 1. 设置当一行文本的长度超过 width 选项设置的宽度时,是否自动换行 ;2. 该选项的值可以是:"none"(不自动换行),"char"(按字符自动换行)和 "word"(按单词自动换行) |
xscrollcommand | 1. 与 scrollbar(滚动条)组件相关联(水平方向) |
yscrollcommand | 1. 与 scrollbar(滚动条)组件相关联(垂直方向) |
在 Text 组件中插入对象,可以使用 window_create()
和 image_create()
方法来插入一个控件或者一个图片
import tkinter as tk
from PIL import Image,ImageTk
root = tk.Tk()
# 创建Text
text = tk.Text(root,width=30,height=10)
text.pack()
# 在 Text 中插入一个按钮控件
test_btn = tk.Button(text,text='test_btn')
text.window_create('insert',window=test_btn)
# 在 Text 中插入一张图片
# 这个方法传入 file 参数的话只支持 gif 图片
img1 = tk.PhotoImage(file='./123.gif')
text.image_create('insert',image=img1)
# 如果需要插入其他格式图片,则需要使用PIL库中的ImageTk方法进行转换
img2 = ImageTk.PhotoImage(Image.open('./123.jpg'))
text.image_create('insert',image=img2)
root.mainloop()
将 state 选项从默认的 "normal" 修改为 "disabled",使得 Text 组件中的内容为“只读”形式。不过需要注意的是,当你需要进行任何修改的时候,记得将 state 选项改回 "normal",否则 insert()
和 delete()
方法都会失效。
text['state'] = 'disabled'
使用search()
方法,可以可以搜索 Text 组件中的内容
search()
方法的 backwards 属性表示是否向后搜索
pos + '+1c'
表示pos后一个字符,同理pos - '-1c'
表示pos前一个字符
import tkinter as tk
from PIL import Image,ImageTk
root = tk.Tk()
# 创建Text
text = tk.Text(root,width=30,height=10)
text.pack()
text.insert('insert','hello\nworld')
lable = tk.Label(root)
lable.pack()
search_val = ''
search_start = 1.0
pos = ''
# 搜索函数
def search():
global search_val,search_start,pos
# 获取搜索框内的内容
val = search_entry.get()
# 判断搜索框内容如果变了的话就重新从头搜索
if search_val != val:
search_start = 1.0
pos = None
search_val = val
# 在Text控件中搜索,返回索引
pos = text.search(val,index=search_start,stopindex='end')
# 如果没有搜索到,则显示 not found,并退出函数
if not pos:
lable['text'] = 'not found'
search_val = ''
return
# 如果搜索到了,就显示索引
lable['text'] = pos
# 并且将下回搜索的开始位置设置到本次搜索结果后一个字符
search_start = pos + '+1c'
# 搜索框与搜索按钮
search_entry = tk.Entry(root)
search_entry.pack()
search_btn = tk.Button(root,text='Search',command=search)
search_btn.pack()
root.mainloop()
通过设置 undo 选项为 True 可以开启 Text 组件的“撤销”功能。然后用 edit_undo()
方法实现“撤销”操作,用 edit_redo()
方法实现“恢复”操作。
这是因为 Text 组件内部有一个栈专门用于记录内容的每次变动,所以每次“撤销”操作就是一次弹栈操作,“恢复”就是再次压栈。
import tkinter as tk
root = tk.Tk()
# 此处开启Text控件的撤销操作
text = tk.Text(root,undo=True)
text.pack()
undo_btn = tk.Button(root,text='撤销',command=lambda :text.edit_undo())
redo_btn = tk.Button(root,text='恢复',command=lambda :text.edit_redo())
undo_btn.pack()
redo_btn.pack()
root.mainloop()
默认情况下,每一次完整的操作将会放入栈中。但怎么样算是一次完整的操作呢?Tkinter 觉得每次焦点切换、用户按下 Enter 键、删除、插入操作的转换等之前的操作算是一次完整的操作。也就是说你连续输入I love Python
的话,一次的“撤销”操作就会将所有的内容删除。
如果不想这样,那么做法就是先将 autoseparators
选项设置为 False(因为这个选项是让 Tkinter 在认为一次完整的操作结束后自动插入“分隔符”),然后绑定键盘事件,每次有输入就用 edit_separator()
方法人为地插入一个“分隔符”:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root, width=40, height=5, autoseparators=False, undo=True, maxundo=10)
text.pack()
def callback(event):
text.edit_separator()
text.bind('<Key>', callback)
def move():
text.edit_undo()
tk.Button(root, text = "撤销", command = move).pack()
root.mainloop()
方法 | 功能 |
---|---|
delete(起始位置,[,终止位置]) | 删除指定区域文本,起始位置 index = 1.0(特别注意),也可以传入一个 window 对象或者一个 image 对象 |
get(起始位置,[,终止位置]) | 获取指定区域文本 |
insert(位置,[,字符串]...) | 将文本插入到指定位置 |
see(位置) | 在指定位置是否可见文本,返回布尔值 |
index(标记) | 返回标记所在的行和列 |
mark_names() | 返回所有标记名称 |
mark_set(标记,位置) | 在指定位置设置标记 |
mark_unset(标记) | 去除标记 |
Text 控件的操作,基本上都与索引有关,Tkinter 提供一系列不同的索引类型:
line.column
:(行.列),例如(1.0)
代表第一行第一列
1.0
代替也是可以的。line.end
:(某一行的末尾),例如(1,end)
代表第一行末尾insert
:对应插入光标的位置。current
:对应与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,它会直到你松开它才响应。end
:对应 Text 组件的文本缓冲区最后一个字符的下一个位置。user-defined marks
:是对 Text 组件中位置的命名。例如insert
和 current
就是两个预先命名好的 marks
,参考后面的 marksuser-defined tags
:代表可以分配给 Text 组件的特殊事件绑定和风格,参考后面的 tagsselection(sel.first,sel.last)
:selection 是一个名为 sel
的特殊 tag,表示当前被选中的范围
sel.first
到 sel.last
来表示这个范围。如果没有选中的内容,那么 Tkinter 会抛出一个TclError 异常。window coordinate("@x,y")
:使用窗口坐标作为索引。
"@%d,%d" % (event.x, event.y)
找到最接近鼠标位置的字符。embedded object name(window,images)
:用于指向在 Text 组件中嵌入的 window 和 image 对象。expressions
:用于修改任何格式的索引,用字符串的形式实现修改索引的表达式。
+ count chars
:将索引向前(->
)移动 count 个字符,可以越过换行符,但不能超过 END
的位置。- count chars
:将索引向后(<-
)移动 count 个字符,可以越过换行符,但不能超过 1.0
的位置+ count lines
:将索引向前(->)移动 count 行,索引会尽量保持与移动前在同一列上,但如果移动后的那一行字符太少,将移动到该行的末尾- count lines
:将索引向后(<-)移动 count 行,索引会尽量保持与移动前在同一列上,但如果移动后的那一行字符太少,将移动到该行的末尾 linestart
:将索引移动到当前索引所在行的起始位置,注意,使用该表达式前边必须有一个空格隔开 lineend
:将索引移动到当前索引所在行的末尾,注意,使用该表达式前边必须有一个空格隔开 wordstart
:将索引移动到当前索引指向的单词的开头,单词的定义是一系列字母、数字、下划线或任何非空白字符的组合,注意,使用该表达式前边必须有一个空格隔开 wordend
:将索引移动到当前索引指向的单词的末尾,单词的定义是一系列字母、数字、下划线或任何非空白字符的组合,注意,使用该表达式前边必须有一个空格隔开+ 5 chars
可以简写成 +5c
index()
方法用于将所有支持的“索引”格式,即line.column
(行、列)的格式
import tkinter as tk
from PIL import Image,ImageTk
root = tk.Tk()
# 创建Text
text = tk.Text(root,width=30,height=10)
text.pack()
text.insert('insert','hello\n')
lable = tk.Label(root,text=f'insert: {text.index('insert')},end: {text.index('end')}')
lable.pack()
root.mainloop()
此时的2.0
表示索引insert也就是光标在第2行第0列;3.0
表示索引end也就是文档结束在第3行第0列
Marks(标记)通常是嵌入到 Text 组件文本中的不可见对象。事实上 Marks 是指定字符间的位置,并跟随相应的字符一起移动。
insert
和 current
是 Tkinter 预定义的特殊 Marks,它们不能够被删除。
insert
用于指定当前插入光标的位置,Tkinter 会在该位置绘制一个闪烁的光标(因此并不是所有的 Marks 都不可见)。current
用于指定与鼠标坐标最接近的位置。不过,如果你紧按鼠标任何一个按钮,它会直到你松开它才响应。你还可以自定义任意数量的 Marks,Marks 的名字是由普通字符串组成,可以是除了空白字符外的任何字符(为了避免歧义,你应该起一个有意义的名字)。使用 mark_set()
方法创建和移动 Marks。
如果你在一个 Mark 标记的位置之前插入或删除文本,那么 Mark 跟着一并移动。删除 Marks 你需要使用 mark_unset()
方法,删除 Mark 周围的文本并不会删除 Mark 本身。
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
text.insert("1.0","HelloWorld")
text.mark_set("my_mark","1.2") # 在 e 和 l 中间插入一个 mark,命名为 my_mark
text.insert("my_mark","123") # my_mark的位置插入123
root.mainloop()
默认插入内容到 Mark,是插入到它的左侧(就是说插入一个字符的话,Mark 向后移动了一个字符的位置)。那能不能插入到 Mark 的右侧呢?其实是可以的,通过 mark_gravity()
方法就可以实现。
text.mark_gravity("my_mark", "left") #默认是 "right"
gs(标签)通常用于改变 Text 组件中内容的样式和功能。你可以修改文本的字体、尺寸和颜色。另外,Tags 还允许你将文本、嵌入的组件和图片与键盘和鼠标等事件相关联。
除了 user-defined tags(用户自定义的 Tags),还有一个预定义的特殊 Tag:sel
用于表示对应的选中内容(如果有的话)。
例如实现获取选中内容:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
lable = tk.Label(root)
lable.pack()
def get_select(e):
w = text.get(text.index('sel.first'),text.index('sel.last'))
lable['text'] = w
text.bind('<ButtonRelease-1>',get_select)
root.mainloop()
你可以自定义任意数量的 Tags,Tags 的名字是由普通字符串组成,可以是除了空白字符外的任何字符。另外,任何文本内容都支持多个 Tags 描述,任何 Tag 也可以用于描述多个不同的文本内容。为指定文本添加 Tags 可以使用 tag_add()
方法:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
text.insert('1.0','HelloWorld')
text.tag_add('my_tag_1','1.1') # 设置my_tag_1到第一行第二个字符
text.tag_config('my_tag_1',background='yellow',foreground='red') # 设置my_tag_1字符背景颜色和字体颜色
text.tag_add('my_tag_2','1.3','1.6') # 设置my_tag_2到第一行的第(四-七)的字符
text.tag_config('my_tag_2',background='black',foreground='white') # 设置my_tag_1字符背景颜色和字体颜色
root.mainloop()
使用 tag_config()
方法可以设置 Tags 的样式,具体参数如下:
选项 | 含义 |
---|---|
background | 1. 指定该 Tag 所描述的内容的背景颜色; 2. 注意:bg 并不是该选项的缩写,在这里 bg 被解释为 bgstipple 选项的缩写 |
bgstipple | 1. 指定一个位图作为背景,并使用 background 选项指定的颜色填充; 2. 只有设置了 background 选项该选项才会生效; 3.默认的标准位图有:'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question' 和 'warning' |
borderwidth | 1. 指定文本框的宽度 ;2. 默认值是 0 ;3. 只有设置了 relief 选项该选项才会生效 ;4. 注意:该选项不能使用 bd 缩写 |
fgstipple | 1. 指定一个位图作为前景色 ;2. 默认的标准位图有:'error', 'gray75', 'gray50', 'gray25', 'gray12', 'hourglass', 'info', 'questhead', 'question' 和 'warning' |
font | 指定该 Tag 所描述的内容使用的字体 |
foreground | 1. 指定该 Tag 所描述的内容的前景色 ;2. 注意:fg 并不是该选项的缩写,在这里 fg 被解释为 fgstipple 选项的缩写 |
justify | 1. 控制文本的对齐方式 ;2. 默认是 "left"(左对齐),还可以选择 "right"(右对齐)和 "center"(居中) ;3. 注意:需要将 Tag 指向该行的第一个字符,该选项才能生效 |
lmargin1 | 1. 设置 Tag 指向的文本块第一行的缩进; 2. 默认值是 0 ;3. 注意:需要将 Tag 指向该文本块的第一个字符或整个文本块,该选项才能生效 |
lmargin2 | 1. 设置 Tag 指向的文本块除了第一行其他行的缩进 ;2. 默认值是 0 ;3. 注意:需要将 Tag 指向整个文本块,该选项才能生效 |
offset | 1. 设置 Tag 指向的文本相对于基线的偏移距离;2. 可以控制文本相对于基线是升高(正数值)或者降低(负数值); 3. 默认值是 0 |
overstrike | 1. 在 Tag 指定的文本范围画一条删除线 ;2. 默认值是 False |
relief | 1. 指定 Tag 对应范围的文本的边框样式 ;2. 可以使用的值有:"sunken", "raised", "groove", "rifge" 或 "flat" ;3. 默认值是 "flat"(没有边框) |
rmargin | 1. 设置 Tag 指向的文本块右侧的缩进; 2. 默认值是 0 |
spacing1 | 1. 设置 Tag 所描述的文本块中每一行与上方的空白间隔; 2. 注意:自动换行不算 ;3. 默认值是 0 |
spacing2 | 1. 设置 Tag 所描述的文本块中自动换行的各行间的空白间隔 ;2. 注意:换行符('\n')不算 ;3. 默认值是 0 |
spacing3 | 1. 设置 Tag 所描述的文本块中每一行与下方的空白间隔 ; 2. 注意:自动换行不算; 3. 默认值是 0 |
tabs | 1. 定制 Tag 所描述的文本块中 Tab 按键的功能 ;2. 默认 Tab 被定义为 8 个字符的宽度 ;3.你还可以定义多个制表位:tabs=('3c', '5c', '12c') 表示前 3 个 Tab 宽度分别为 3厘米,5厘米,12厘米,接着的 Tab 按照最后两个的差值计算,即:19厘米,26厘米,33厘米 ;4.你应该注意到了,它上边 'c' 的含义是“厘米”而不是“字符”,还可以选择的单位有 'i'(英寸),'m'(毫米)和 'p'(DPI,大约是 '1i' 等于 '72p');5.如果是一个整型值,则单位是像素 |
underline | 1. 该选项设置为 True 的话,则 Tag 所描述的范围内文本将被画上下划线 ;2. 默认值是 False |
wrap | 1. 设置当一行文本的长度超过 width 选项设置的宽度时,是否自动换行; 2. 该选项的值可以是:"none"(不自动换行),"char"(默认)(按字符自动换行)和 "word"(按单词自动换行) |
Tags 还支持事件绑定,使用的是 tag_bind()
的方法。
下边例子中我们将文本("Python.com")与鼠标事件进行绑定,当鼠标进入该文本段的时候,鼠标样式切换为 "arrow" 形态,离开文本段的时候切换回 "xterm" 形态。当触发鼠标“左键点击操作”事件的时候,使用默认浏览器打开Python的首页(https://www.python.org/):
import tkinter as tk
import webbrowser
root = tk.Tk()
text = tk.Text(root, width=40, height=5)
text.pack()
text.insert("insert", "I love Python.com!")
text.tag_add("link", "1.7", "1.17")
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("https://www.python.org/")
text.tag_bind("link", "<Enter>", show_arrow_cursor)
text.tag_bind("link", "<Leave>", show_xterm_cursor)
text.tag_bind("link", "<Button-1>", click)
root.mainloop()