Search code examples
python-3.xtkintertkinter-text

Tkinter: highlight selected text with color on a keyboard input


I am new to Tkinter and I am trying to build an annotation tool wherein I want the text selected by the user to get highlighted with some color when a keyboard key is pressed. This is my code until now.

from tkinter import *
import tkinter as tk
from tkinter import Frame, Menu
from tkinter import ttk  

class StartPage(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master) 
        self.results_field = tk.Text(self)
        self.results_field.insert('insert','sometext'*100)
        self.results_field.config(height=10,spacing1=5,yscrollcommand=True,wrap='word')
        self.results_field.tag_configure("start", background="black",foreground='red')
        self.results_field.bind('<KeyPress>', self.onKeyPress)
        self.results_field.pack()
    def onKeyPress(self,event):
        self.results_field.tag_add("start", "sel.first", "sel.last")

class App(tk.Tk):
    def __init__(self):
       tk.Tk.__init__(self)
       self._frame = None
       self.switch_frame(StartPage)
    def switch_frame(self, frame_class):
        new_frame = frame_class(self)
        self._frame = new_frame
        self._frame.pack()
def main():
   app=App()
   app.geometry("1000x500") 
   app.mainloop()
if __name__ == '__main__':
    main()

I posted the whole code, lest I may have erred anywhere else. Any help would be highly appreciated. Thanks in advance :)


Solution

  • Oh wow you are so close. The only thing is that when you press a key the Text widget also has an action to perform, and most of the time that action involves removing the selected text. I'm sure you have noticed that your code works fine with keys that don't affect the text, like Shift and Ctrl. To make it work with the rest you need to disable the Text action. You do that by adding a return "break" to the keypress function.

    def onKeyPress(self,event):
        # todo: add try block to catch nothing selected error
        self.results_field.tag_add("start", "sel.first", "sel.last")
        return "break" # Disable Text action