Reputation: 18953
I am attempting to modify some amazing code provided by Bryan Oakley that highlights (tags) words in a tkinter Text widget on a ButtonRelease-1
event.
Instead of highlighting a single word, I'd like to click some text, drag my mouse to another area on the same line (left or right), and highlight that full range from that ranges wordstart
and wordend
boundaries.
For example, if I click the end of the first line after tk in the code below, drag my mouse to the p of the word import and release my mouse button, I want the tag to expand to capture the full range from 1.0
to 1.20
.
The below code uses two tk.StringVar
to capture start and end strings but from those two indices obtained, how would I apply these start and end points to the range and then expand to highlight up to the wordstart
and wordend
range?
import tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.text = tk.Text(self, wrap="none")
self.text.pack(fill="both", expand=True)
self.start = tk.StringVar()
self.end = tk.StringVar()
self.text.bind("<Button-1>", self.button_down)
self.text.bind("<ButtonRelease-1>", self.button_up)
#self.text.bind("<B1-Motion>", self._on_click)
self.text.tag_configure("highlight", background="green", foreground="black")
with open(__file__, "rU") as f:
data = f.read()
self.text.insert("1.0", data)
def button_down(self, event):
self.start.set(self.text.index('@%s,%s' % (event.x, event.y)))
print(self.start.get())
def button_up(self, event):
self.end.set(self.text.index('@%s,%s' % (event.x, event.y)))
print(self.end.get())
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
Upvotes: 4
Views: 1957
Reputation: 18953
Posting "my" solution (based 99% on Bryan's code and help). If user highlights mouse from left-to-right vs right-to-left, I wasn't sure the "best" way to handle that so I compared the indexes as floats to see which was greater or less than and handled the wordstart
and wordend
accordingly.
import tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.text = tk.Text(self, wrap="none")
self.text.pack(fill="both", expand=True)
self.text.bind("<Button-1>", self.button_down)
self.text.bind("<ButtonRelease-1>", self.button_up)
self.text.tag_configure("highlight", background="green", foreground="black")
with open(__file__, "rU") as f:
data = f.read()
self.text.insert("1.0", data)
def button_down(self, event):
self.xy_down = self.text.index('@%s,%s' % (event.x, event.y))
self.start = self.text.index('@%s,%s' % (event.x, event.y))
def button_up(self, event):
self.stop = self.text.index('@%s,%s' % (event.x, event.y))
self.xy_up = self.text.index('@%s,%s' % (event.x, event.y))
if self.xy_down == self.xy_up:
self.text.tag_remove('highlight', 1.0, 'end')
self.text.tag_add("highlight", 'insert wordstart', 'insert wordend')
elif float(self.start) > float(self.stop):
#print('Highlight right to left')
self.begin = self.text.index('%s wordend' % (self.start))
self.end = self.text.index('%s wordstart' % (self.stop))
self.text.tag_remove('highlight', 1.0, 'end')
self.text.tag_add("highlight", self.end, self.begin)
print(self.start, self.stop, self.begin, self.end)
elif float(self.start) < float(self.stop):
#print('Highlight left to right')
self.begin = self.text.index('%s wordstart' % (self.start))
self.end = self.text.index('%s wordend' % (self.stop))
self.text.tag_remove('highlight', 1.0, 'end')
self.text.tag_add("highlight", self.begin, self.end)
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
Upvotes: 1
Reputation: 386325
You can append "wordstart"
or "wordend"
to any valid index. Also, you don't need to use a StringVar
-- it adds complexity and provides no extra value over a normal variable:
Here's one way to do it:
def button_down(self, event):
self.start = self.text.index('@%s,%s wordstart' % (event.x, event.y))
def button_up(self, event):
self.end = self.text.index('@%s,%s wordend' % (event.x, event.y))
self.text.tag_add("highlight", self.start, self.end)
Upvotes: 7