[英]Python - How To Get Cursor Position in Tkinter Text Widget
我想獲取Tkinter.Text插入點的光標位置(行和列),但針對以下特定情況。
問題:我的文本編輯器項目需要對Tkinter.Text自定義撤消/重做。 我為下面的“測試一”和“測試二”輸入了相同的字符串,但是由於Tkinter給出的KeyRelease事件處理程序中的列變量不一致,因此撤消操作不一致。 問題似乎是我輸入的速度太快而無法進行第二次測試,這會產生錯誤的列值。 你能幫我找到問題嗎?
減少錯誤的兩個測試過程:
測試一
結果:工作正常。 (對我來說至少。重點:緩慢鍵入。)
測試二
結果:獲取錯誤的列,並且無法正確撤消。 (如果您起初沒有看到錯誤,請重新啟動腳本並重復此步驟,有時快速鍵入有時效果很好。我通常最多嘗試3至4次就可以了。)
問題:這是Tkinter中的bug,還是我不了解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()
我終於弄清楚發生了什么事,並且與Tkinter無關,但與所有工具包無關。 我現在可以誠實地說,我可以在“最佳編程實踐”中添加以下內容:
不要通過綁定鍵釋放方法來處理鍵事件,而是使用按鍵方法來處理鍵
為什么?
這實際上不是編程問題,而是硬件問題。 當按下一個鍵時,物理鍵會下降。 有一個彈簧可以將鑰匙向上推。 如果那彈簧或鍵盤上的任何東西使鍵慢了200秒鍾,則即使每分鍾輸入60個單詞也可能導致按一種順序鍵入的鍵又以另一種順序返回。 發生這種情況的原因是,彈簧可能略厚,更硬,用得過重甚至是摩卡咖啡會引起更大的阻力。
大小寫也會受到影響。 必須同時按下Shift鍵和另一個鍵以獲得大寫字母。 但是,如果您在釋放鍵時處理鍵,則Shift鍵彈起的速度可能比您要大寫的字符鍵的彈起速度快,這將導致小寫字母的出現。 這也允許字符反轉。 如果在鍵入字符時檢查字符的位置,由於這個原因,您也會得到錯誤的位置。
堅持按鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.