在 tkinter 中进行多项选择
Making multiple selections in tkinter
有什么方法可以在 tkinter 中制作多个 selection 吗?
代码如下:
from tkinter import *
root = Tk()
text = Text(root , width = 65 , height = 20 , font = "consolas 14")
text.pack()
text.insert('1.0' , "This is the first line.\nThis is the second line.\nThis is the third line.")
mainloop()
在这里,我希望能够从任何我想要的地方select多条文本。
这是一张解释我的意思的图片 (GIF):
有什么方法可以在 tkinter 中实现这个吗?
如果有人能帮助我就太好了。
简答:将每个文本小部件的 exportselection
属性设置为 False
Tkinter 允许您使用 exportselection
文本小部件以及条目和列表框小部件的配置选项来控制此行为。将其设置为 False
可防止将选择导出到 X 选择,从而允许小部件在其他小部件获得焦点时保留其选择。
例如:
import tkinter as tk
...
text1 = tk.Text(..., exportselection=False)
text2 = tk.Text(..., exportselection=False)
您可以在此处找到更多信息:http://tcl.tk/man/tcl8.5/TkCmd/options.htm#M-exportselection
我做了一个简短的演示,按住 Control
键你可以 select 多个文本。检查这个:
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)
删除每个 selection 但是当一行中的第一个 selection 被删除时,索引发生变化,使得随后的 delete
删除未 selected 的索引(或超出特定行的范围。
我不得不另辟蹊径 - 首先从第一个 selected 到最后一个 selected 删除,就像 BackSpace
默认情况下所做的那样,然后放回去中间每个未select编辑的部分。 Text.tag_ranges
以这种方式为您提供范围列表 select:
[start1, end1, start2, end2, ...]
其中每个条目都是 <textindex object>
和 string
属性(索引)。所以你可以提取end1
和start2
之间,end2
和start3
之间的文本,等等,并将它们存储到一个变量中(not_deleting
) 这样您就可以将它们重新插入到文本中。
应该有更好更简洁的解决方案,但目前就是这样...希望对您有所帮助。
对于张巧轩提出的delete_
方法,我建议在循环中使用Text.tag_nextrange
方法:
def delete_sel(self):
while 1:
result = self.tag_nextrange(tk.SEL, 1.0)
if result :
self.delete(result[0] , result[1])
else :
break
对于那些想要添加缺失功能的人:
改变滑动方向时的选择更正
考虑双击
看这里:French site
有什么方法可以在 tkinter 中制作多个 selection 吗?
代码如下:
from tkinter import *
root = Tk()
text = Text(root , width = 65 , height = 20 , font = "consolas 14")
text.pack()
text.insert('1.0' , "This is the first line.\nThis is the second line.\nThis is the third line.")
mainloop()
在这里,我希望能够从任何我想要的地方select多条文本。
这是一张解释我的意思的图片 (GIF):
有什么方法可以在 tkinter 中实现这个吗?
如果有人能帮助我就太好了。
简答:将每个文本小部件的 exportselection
属性设置为 False
Tkinter 允许您使用 exportselection
文本小部件以及条目和列表框小部件的配置选项来控制此行为。将其设置为 False
可防止将选择导出到 X 选择,从而允许小部件在其他小部件获得焦点时保留其选择。
例如:
import tkinter as tk
...
text1 = tk.Text(..., exportselection=False)
text2 = tk.Text(..., exportselection=False)
您可以在此处找到更多信息:http://tcl.tk/man/tcl8.5/TkCmd/options.htm#M-exportselection
我做了一个简短的演示,按住 Control
键你可以 select 多个文本。检查这个:
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)
删除每个 selection 但是当一行中的第一个 selection 被删除时,索引发生变化,使得随后的 delete
删除未 selected 的索引(或超出特定行的范围。
我不得不另辟蹊径 - 首先从第一个 selected 到最后一个 selected 删除,就像 BackSpace
默认情况下所做的那样,然后放回去中间每个未select编辑的部分。 Text.tag_ranges
以这种方式为您提供范围列表 select:
[start1, end1, start2, end2, ...]
其中每个条目都是 <textindex object>
和 string
属性(索引)。所以你可以提取end1
和start2
之间,end2
和start3
之间的文本,等等,并将它们存储到一个变量中(not_deleting
) 这样您就可以将它们重新插入到文本中。
应该有更好更简洁的解决方案,但目前就是这样...希望对您有所帮助。
对于张巧轩提出的delete_
方法,我建议在循环中使用Text.tag_nextrange
方法:
def delete_sel(self):
while 1:
result = self.tag_nextrange(tk.SEL, 1.0)
if result :
self.delete(result[0] , result[1])
else :
break
对于那些想要添加缺失功能的人:
改变滑动方向时的选择更正
考虑双击
看这里:French site