有关 Text 组件的基本用法在上一篇博客中已经讲述,这里不再赘述。
这里将讲述 Text 组件的实用技巧:
目录
①判断内容是否发生变化
比如说做一个笔记本 (.txt 的那个记事本) 程序,或者重新做一个 IDLE。它们都有输入框,有输入框当程序在关闭的时候应该自动检测内容是否发生改变,如果有改变但用户并没有保存的时候,应该提醒用户是否保存。
我们这个例子是通过验证文本的 md5 摘要来判断文本是否发生改变。
from tkinter import *
import hashlib #获得md5的值要用该库
root = Tk()
text = Text(root, width=30, height=5)
text.pack()
text.insert(INSERT, 'I love study')
contents = text.get('1.0', END)
def getSig(contents):
n = hashlib.md5(contents.encode())
return n.digest() #只需要得到md5值n的简单摘要即可
sig = getSig(contents)
def check(): #点下检查的时候,会重新获得一次contents的内容,将原来的contents进行一个md5的hash,获得它的md5的值;同时也获得之后contents的md5的值,将两者进行对比。由于一个内容只能产生一个唯一的散列,因此若不一样,就说明内容发生了改变。
contents = text.get('1.0', END)
if sig != getSig(contents):
print("内容发生变动")
else:
print("内容没有发生变动")
Button(root, text="检查", command=check).pack()
mainloop()
②查找操作
查找使用 search 方法,使用 search 方法可以对 text 的内容进行搜索。
不过默认是只找到第一个位置。下面是一个可以全文搜索 字母y 的例子:
from tkinter import *
import hashlib #获得md5的值要用该库
root = Tk()
text = Text(root, width=30, height=5)
text.pack()
text.insert(INSERT, 'I enjoy studying Python')
def getIndex(text, index): #要把任何支持的格式转化为默认行列字符串的格式可以使用Text组件的index()方法
return tuple(map(int, str.split(text.index(index), '.'))) #将转化好的转化成一个元组的形式返回
start = '1.0'
while True:
pos = text.search("y", start, stopindex=END)
if not pos: #找不到就跳出循环
break
print("找到了,位置是:", getIndex(text, pos)) #把找到的位置转化为人类能读懂的位置
start = pos + '+1c' #将start的位置指向下一个字符
mainloop()
③Text 组件还支持恢复和撤销的操作
我们可以简单设置 Text 组件的 undo 选项为 True 开启其撤销功能,然后使用 edit_undo() 方法来实现撤销操作,用 edit_redo() 的方法来实现其恢复操作。
from tkinter import *
root = Tk()
text = Text(root, width=30, height=5, undo=True)
text.pack()
text.insert(INSERT, 'I enjoy studying Python')
def show():
text.edit_undo()
Button(root, text='撤销', command=show).pack()
mainloop()
这是因为 Text 组件内部有一个栈专门用于记录内容的每次变动,所以每次撤销操作就是一次弹栈操作,恢复就是再次压栈。
默认情况下,每一次完整操作将会放入栈中但怎么样才算是一次完整的操作呢?Tkinter 觉得每次焦点切换,用户按下 Enter 键。删除\插入操作的转换等之前的操作算是一次完整的操作。
自定义撤销操作
那我们能不能自定义呢?比如说我希望插入一个字符就算一次完整的操作,然后每次点击撤销就去掉一个字符。
当然可以,做法就是先将 autoseparators 选项设置为 False(因为这个选项是让 Tkinter 在认为一次完整的操作结束后自动插入 “分隔符”),然后绑定键盘事件,每次有输入就用 edit_separator() 方法人为地插入一个 “分隔符”:
from tkinter import *
root = Tk()
text = Text(root, width=30, height=5, undo=True, autoseparators=False)
text.pack()
text.insert(INSERT, 'I enjoy studying Python')
def callback(event):
text.edit_separator()
text.bind('<Key>', callback) #一旦有键盘事件就人为地插入一个分隔符
def show():
text.edit_undo()
Button(root, text='撤销', command=show).pack()
mainloop()