在 tkinter 中选择多个文本

问题描述

有没有办法在 tkinter 中选择多个文本?

代码如下:

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()

在这里,我希望能够从任何我想要的地方选择多个文本。

这是一个解释我的意思的图像(GIF):

enter image description here

有没有办法在 tkinter 中实现这一点?

如果有人能帮助我就好了。

解决方法

我做了一个简短的演示,按住 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,...]

其中每个条目都是一个带有 <textindex object> 属性(索引)的 string。所以你可以将end1start2之间、end2start3之间的文本提取到最后,并将它们存储到一个变量(not_deleting ) 以便您可以将它们重新插入文本中。

应该有更好、更简洁的解决方案,但现在就是这样……希望它有所帮助。

,

简答:将每个 Text 小部件的 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