Is there any way to select multiple text in tkinter?
Here's the code:
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()
Here, I want be able to select multiple text from where ever I want.
Here is an Image(GIF) that explains what I mean:
Is there any way to achieve this in tkinter?
It would be great if anyone could help me out.
I made a short demo, with Control
key hold you could select multiple text. Check this:
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()
So I was trying to delete each selection with the Text.delete(index1, index2)
but when the first selection in one line is deleted, the indices changes, making the subsequent delete
deleting indices not selected (or out of range in the particular line.
I had to work around another way - first deleting from the first selected to the last selected, just like what BackSpace
would do by default, then put back every unselected part in the middle. The Text.tag_ranges
gives you a list of ranges selected in this way:
[start1, end1, start2, end2, ...]
where each entry is a <textindex object>
with a string
property (the index). So you can extract the text between end1
and start2
, between end2
and start3
, etc. to the end, and store these into a variable ( not_deleting
) so you can insert them back into the text.
There should be better and neater solutions but for now this is what it is... Hope it helps.
Short answer: set the exportselection
attribute of each Text widget to False
Tkinter gives you control over this behaviour with the exportselection
configuration option for the Text widget as well as the Entry and Listbox widgets. Setting it to False
prevents the export of the selection to the X selection, allowing the widget to retain its selection when a different widget gets focus.
For example:
import tkinter as tk
...
text1 = tk.Text(..., exportselection=False)
text2 = tk.Text(..., exportselection=False)
you can find more info here: http://tcl.tk/man/tcl8.5/TkCmd/options.htm#M-exportselection
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.