python - 在 tkinter 中进行多项选择

标签 python tkinter selection

有什么办法可以在 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属性(索引)。所以你可以提取 end1 之间的文本和 start2 , 在 end2 之间和 start3等到最后,并将它们存储到一个变量 ( not_deleting ) 中,以便您可以将它们插入回文本中。

应该有更好、更简洁的解决方案,但目前就是这样……希望对您有所帮助。

关于python - 在 tkinter 中进行多项选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66380959/

相关文章:

python - 如何使用 xsel 获取选定的文本 - Python

python - 如何在numpy中找到给定行值的列索引?

python - 通过 SCAPY 使用特定私钥解密 SSL/TLS

python - 如何将数据帧从 .py 文件导入到 .ipynb 文件?

python - 在 Tkinter 中打开新窗口会卡住程序(python 3.6)

python - Tkinter 和线程

python - 如何通过 OpenCV 验证标记的特征是否正确跟踪视频中的对象?

python - Tkinter - 切换到不同页面时如何重置网格行配置

delphi - SysListView32类似鼠标选择矩形

ios - UITableView didSelectRowAtIndexPath 从未调用过