Search code examples
pythonreplacetkinterbackspacestrikethrough

Changing Backspace effect in Tkinter text widget


I am looking for a way to change the Backspace key effect in a Tkinter text widget. I am monitoring the key events in the Text Window from Tkinter, and I would need to find a way to :

  • Disable the effect of the Backspace key, but still be able know it was typed

  • Strikethrough the character the user was intending to delete

I have no idea where to start with that. I can single out the Backspace event, but do not know how to prevent it from deleting a character. I also don't know how affect the input in real time (apply a strikethrough 'style' to the character(s) as the user is writing)

Here is what I have for now, but that's not much :

from Tkinter import *
import tkFileDialog
root=Tk()
root.title("TextnonEdit")
text=Text(root)
text.grid()

def keepit(key):
    print key.keysym
    if key.keysym == "BackSpace":
        print "do not delete, strikethrough"

# Bind entry to keypress
text.bind("<Key>", keepit)

def saveas():
    global text
    t = text.get("1.0", "end-1c")
    savelocation=tkFileDialog.asksaveasfilename()
    file1=open(savelocation, "w+")
    file1.write(t)
    file1.close()

button=Button(root, text="Save", command=saveas)
button.grid()
root.mainloop()

Thanks in advance for any answer !


Solution

  • The problem can be solved by doing the following:

    1. create a tag on the text widget with the overstrike attribute set to true
    2. create a binding on the backspace character to apply the tag
    3. have the bound function return "break" to prevent the default behavior

    Example:

    import Tkinter as tk
    
    class Example(tk.Frame):
        def __init__(self, parent):
            tk.Frame.__init__(self, parent)
    
            self.text = tk.Text(self)
            self.text.pack(fill="both", expand=True)
    
            # add a tag that lets us apply the overstrike attribute
            self.text.tag_configure("overstrike", overstrike=True)
    
            # add a binding on the backspace key
            self.text.bind("<BackSpace>", self.handleBackspace)
    
        def handleBackspace(self, event):
            # add the overstrike to the character before the
            # insertion cursor
            self.text.tag_add("overstrike", "insert-1c", "insert")
    
            # move the cursor to the previous position
            self.text.mark_set("insert", "insert-1c")
    
            # prevent the default behaviour
            return "break"
    
    if __name__ == "__main__":
        root = tk.Tk()
        Example(root).pack(fill="both", expand=True)
        root.mainloop()