Tkinter Text widget reading input (how to do overwrite mode?)
Jeff Epler
jepler at unpythonic.net
Mon Apr 29 14:20:06 EDT 2002
On Mon, Apr 29, 2002 at 10:00:39AM -0500, Jeff Epler wrote:
> I have implemented an 'overwrite mode' in the Text widget in tcl.
> Conversion to Python is left as an exercise to the reader.
Okay, I can't stand an unfinished exercise. In my "testing", I decided
that it could stand to be a little smarter, in particular when the
insertion point is at the end of a line and I'm in overwrite mode, I don't
expect the newline to be removed to make room for the new character.
Since arbitrary new attributes can be hung on a Python class, there's no
fooling around with a fake tag on the text widget .. yay Python!
Things still behave slightly oddly when the widget contains the
selection. If the overlined characters are selected and | shows the
insertion point, here's what happens when you overwrite "x":
____
abc|defghijk
becomes
abcx|ijk
This suggests that a test should be made for whether "nextchar" lies
inside the selection -- if so, the step inside Text's KeyPress binding
which deletes the selected text will delete it for us.
# --- overwritetext.py
import Tkinter
def comparable_index(index):
return map(int, index.split("."))
class OverwriteText(Tkinter.Text):
def __init__(self, *args, **kw):
Tkinter.Text.__init__(self, *args, **kw)
tags = list(self.bindtags())
idx = tags.index("Text")
tags[idx:idx] = ["OverwriteText"]
self.bindtags(tuple(tags))
self.is_overwrite = 0
if not self.bind_class("OverwriteText"):
self._init_bindings()
def _init_bindings(self):
self.bind_class("OverwriteText", "<KeyPress>",
lambda evt: OverwriteText.KeyPress(evt.widget, evt))
self.bind_class("OverwriteText", "<Insert>",
lambda evt: OverwriteText.Insert(evt.widget, evt))
def toggle_overwrite(self):
self.is_overwrite = not self.is_overwrite
def KeyPress(self, evt):
if self.is_overwrite:
eol = self.index("insert lineend")
nextchar = self.index("insert + %dc" % len(evt.char))
eol_num = comparable_index(eol)
nextchar_num = comparable_index(nextchar)
if eol_num < nextchar_num:
index = eol
else:
index = nextchar
self.delete("insert", index)
def Insert(self, evt):
self.toggle_overwrite()
return "break" # Don't insert clipboard text
def _test():
import sys
t = OverwriteText()
t.pack()
t.insert(0.0, open(sys.argv[0]).read())
t.mainloop()
if __name__ == '__main__': _test()
More information about the Python-list
mailing list