There are two parts to this question. The first part is related to how to
delete more than one character at a time. The second part is how to use that in a binding tied to the backspace keys
Deleting more than one character
The delete
method of the text widget takes two indexes, and will delete
the characters between those indexes. Tkinter text indexes can be relative
by applying modifiers to an index. For example, to reference the four
characters before the insertion point you can use the index "insert"
plus the modifier "-4 chars"
.
Example:
self.text.delete("insert -4 chars", "insert")
Because these indexes are normal strings, you can use string formatting if you want to use a variable.
Example:
tabWidth = 4
self.text.delete("insert -%d chars" % tabWidth, "insert")
Using the function with a binding
To run a function when the user presses the backspace key, you can bind
a function to the <BackSpace>
event. This function will be passed
one argument which represents the event.
For example:
self.text.bind("<BackSpace>", self.do_backspace)
...
def do_backspace(self, event):
...
An important part of doing custom bindings to standard keys is to know that your binding by default will not replace the default behavior. For example, if your binding deletes one character and then returns, two characters will get deleted because your binding will remove one and the default binding will remove one.
The way to override this behavior is to return the string "break"
. Because your custom binding happens before the default binding, the default binding will see that you returned "break" and do nothing. This makes it very simple to either override the default behavior or do additional work while keeping the default behavior.
Putting it all together, this is how you can define a function that deletes the previous four characters if they are four consecutive spaces, and do the default behavior if not:
def do_backspace(self, event):
# get previous <tabWidth> characters; if they are all spaces, remove them
previous = self.text.get("insert -%d chars" % self.tabWidth, "insert")
if previous == " " * self.tabWidth:
self.text.delete("insert-%d chars" % self.tabWidth, "insert")
# return "break" so that the default behavior doesn't happen
return "break"
# if we get to here, we'll just return. That allows the default
# behavior to run
Putting it all together
Here is a complete working example that will insert four spaces when you
press tab, and remove four spaces when you press backspace:
import tkinter as tk
def do_tab(event):
text.insert("insert", " " * tabWidth)
# return "break" so that the default behavior doesn't happen
return "break"
def do_backspace(event):
# get previous <tabWidth> characters; if they are all spaces, remove them
previous = text.get("insert -%d chars" % tabWidth, "insert")
if previous == " " * tabWidth:
text.delete("insert-%d chars" % tabWidth, "insert")
# return "break" so that the default behavior doesn't happen
return "break"
# if we get to here, we'll just return. That allows the default
# behavior to run
root = tk.Tk()
tabWidth = 4
text = tk.Text(root)
text.pack(fill="both", expand=True)
text.bind("<Tab>", do_tab)
text.bind("<BackSpace>", do_backspace)
root.mainloop()