如何在tkinter Text组件中获取当前光标位置?绑定事件返回旧位置问题
解决tkinter Text组件光标位置获取滞后的问题
这是个很典型的tkinter事件绑定小坑!你的代码之所以打印的是之前的光标位置,核心原因是:tkinter默认的<Key>和<Button-1>事件是在实际操作完成前触发回调函数的。
举个例子:
- 当你按下键盘按键时,
<Key>事件会在字符插入到Text组件、光标移动到新位置之前就调用check_pos,所以你拿到的是按键按下前的旧位置; - 同理,点击鼠标左键时,
<Button-1>事件是在tkinter把光标移动到点击位置之前触发的,自然也只能拿到之前的位置。
两种可行的解决方案:
方案1:改用释放类事件
把绑定的事件改成<KeyRelease>和<ButtonRelease-1>,这类事件是在操作完成后触发的,此时光标已经更新到最新位置:
import tkinter as tk def check_pos(event): print(t.index(tk.INSERT)) root = tk.Tk() t = tk.Text(root) t.pack() # 按键释放时触发,此时字符已插入、光标已移动 t.bind("<KeyRelease>", check_pos) # 鼠标左键释放时触发,此时光标已移动到点击位置 t.bind("<ButtonRelease-1>", check_pos) root.mainloop()
方案2:用after_idle延迟执行获取操作
如果一定要保留原来的<Key>和<Button-1>事件绑定,可以用root.after_idle()让获取光标位置的操作延迟到tkinter处理完所有当前事件后再执行:
import tkinter as tk def check_pos(event): # 让tkinter先处理完插入字符、移动光标这些操作,再获取位置 root.after_idle(lambda: print(t.index(tk.INSERT))) root = tk.Tk() t = tk.Text(root) t.pack() t.bind("<Key>", check_pos) t.bind("<Button-1>", check_pos) root.mainloop()
after_idle会把传入的函数加入到tkinter的事件队列末尾,等所有当前的UI操作都完成后再执行,这样就能拿到最新的光标位置了。
内容的提问来源于stack exchange,提问作者Neil
相关产品推荐
相关产品推荐

