【发布时间】:2014-09-11 22:44:05
【问题描述】:
我想获取一个Tkinter.Text的插入点的光标位置(行列),但是针对下面的具体情况。
问题:我的文本编辑器项目需要为 Tkinter.Text 自定义撤消/重做。我为下面的测试一和测试二输入了相同的字符串,但是由于 Tkinter 给出的 KeyRelease 事件处理程序中的列变量不一致,撤消操作不一致。问题似乎是我输入得太快而无法进行第二次测试,这会产生错误的列值。你能帮我找出问题吗?
重现错误的两个测试过程:
测试一个
- 慢慢输入这个字符串:'一二三'
- 按 F1 可查看撤消的每个单词。
结果:工作正常。 (至少对我来说。重点:慢慢打字。)
测试二
- 尽可能快地键入相同的字符串:'一二三'
- 按 F1 可查看撤消的每个单词。
结果:获取错误的列并且无法正确撤消。 (如果您一开始没有看到错误,请重新启动脚本并重复此步骤,它有时可以在快速输入时正常工作。我通常最多尝试 3 到 4 次。)
问题:这是 Tkinter 中的错误,还是我不了解 Tkinter 中的某些特定内容会为我的撤消/重做记录生成一致的列?
from Tkinter import *
class TextView(Text):
def __init__(self, root):
Text.__init__(self, root)
self.history = History(self)
self.bind("<KeyRelease>", self.keyRelease)
# used to capture a char at a time in keyRelease. If space char is pressed it creates a Word object and adds it to undo/redo history.
self.word = ""
def keyRelease(self, event):
if event.keysym == "space":
self.word += " "
self.makeWordRecord()
else:
self.word += event.char
def makeWordRecord(self, ):
if len(self.word):
index = self.index(INSERT)
wordEvent = Word(index, self.word)
self.history.addEvent(wordEvent)
self.word = ""
def undo(self, event):
self.makeWordRecord()
self.history.undo()
def redo(self, event):
self.history.redo()
class History(object):
def __init__(self, text):
self.text = text
self.events = []
self.index = -1
# create blank document record, line one, column one, no text
self.addEvent(Word("1.0", ""))
def addEvent(self, event):
if self.index +1 < len(self.events):
self.events = self.events[:self.index +1]
self.events.append(event)
self.index +=1
def undo(self):
if self.index > 0:
self.events[self.index].undo(self.text)
self.index -=1
def redo(self):
if self.index +1 < len(self.events):
self.index +=1
self.events[self.index].redo(self.text)
class Word(object):
def __init__(self, index, word):
self.index = index
self.word = word
def undo(self, text):
line = self.index.split(".")[0]
column = int(self.index.split(".")[-1])
startIndex = line + "." + str(column - len(self.word))
endIndex = line + "." + str(int(column))
text.delete(startIndex, endIndex)
def redo(self, text):
line = self.index.split(".")[0]
column = int(self.index.split(".")[-1])
startIndex = line + "." + str(column - len(self.word))
text.insert(startIndex, self.word)
if __name__ == "__main__":
root = Tk()
root.geometry("400x200+0+0")
textView = TextView(root)
textView.pack()
root.bind("<F1>", textView.undo)
root.bind("<F2>", textView.redo)
root.mainloop()
【问题讨论】:
-
到目前为止,您做了哪些故障排除?你有没有例如输入
prints 看看记录了什么?看了history的内容? -
我发现了问题。我刚刚学会了永远不要在任何工具包的密钥发布中处理关键事件。请参阅我的答案以了解原因。
标签: python python-2.7 tkinter