我做了一个简短的演示,使用Control 键可以选择多个文本。检查这个:
import tkinter as tk
class SelectableText(tk.Text):
def __init__(self, master, **kwarg):
super().__init__(master, **kwarg)
self.down_ind = ''
self.up_ind = ''
self.bind("<Control-Button-1>", self.mouse_down)
self.bind("<B1-Motion>", self.mouse_drag)
self.bind("<ButtonRelease-1>", self.mouse_up)
self.bind("<BackSpace>", self.delete_)
def mouse_down(self, event):
self.down_ind = self.index(f"@{event.x},{event.y}")
def mouse_drag(self, event):
self.up_ind = self.index(f"@{event.x},{event.y}")
if self.down_ind and self.down_ind != self.up_ind:
self.tag_add(tk.SEL, self.down_ind, self.up_ind)
self.tag_add(tk.SEL, self.up_ind, self.down_ind)
def mouse_up(self, event):
self.down_ind = ''
self.up_ind = ''
def delete_(self, event):
selected = self.tag_ranges(tk.SEL)
if len(selected) > 2:
not_deleting = ''
for i in range(1, len(selected) - 1):
if i % 2 == 0:
not_deleting += self.get(selected[i-1].string, selected[i].string)
self.delete(selected[0].string, selected[-1].string)
self.insert(selected[0].string, not_deleting)
return "break"
root = tk.Tk()
text = SelectableText(root, width=50, height=10)
text.grid()
text.insert('end', "This is the first line.\nThis is the second line.\nThis is the third line.")
root.mainloop()
所以我试图用Text.delete(index1, index2) 删除每个选择,但是当删除一行中的第一个选择时,索引会发生变化,导致后续delete 删除索引未被选中(或超出特定行的范围.
我不得不用另一种方法解决 - 首先从第一个选择到最后一个选择删除,就像默认情况下BackSpace 所做的那样,然后将每个未选择的部分放回中间。 Text.tag_ranges 为您提供以这种方式选择的范围列表:
[start1, end1, start2, end2, ...]
其中每个条目都是带有string 属性(索引)的<textindex object>。因此,您可以将end1 和start2 之间、end2 和start3 之间的文本提取到最后,并将它们存储到一个变量(not_deleting)中,这样您就可以将它们重新插入到文本中.
应该有更好更整洁的解决方案,但现在就是这样......希望它有所帮助。