Kronope Kronope - 12 days ago 6
Python Question

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 !

Answer

The problem can be solved by doing the following:

  1. create a tag on the text widget with the configure 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 behaviour

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()