I am wanting to create bindings that let me press tab to insert a predefined number of spaces, and then press backspace to delete that many spaces, based on a variable.
How can I delete a pre-determined number of spaces when the user presses the backspace key? I don't know how to delete multiple characters, and when I've attempted to solve this, the binding deletes the wrong number of characters.
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
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")
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
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With