Tkinter 在绑定到 <Key> 时双重打印字符
Tkinter double-prints characters when binding to <Key>
我有一系列 16 个 Tk Entry 小部件,我想将 事件绑定到任何具有可见效果的东西(如 a、7 和 *),而任何键没有立即可见效果有他们的 keysym 表示代替(Return,Tabx,Shift_L,等等...)
如果我将 绑定到这些 Entry 小部件中的每一个,任何具有可见 event.char 双重打印。任何带有隐形的东西都不会。如果我将 绑定到根,则不会发生这种情况。
考虑到我的实际程序有几个按钮和一个 canvas,将 绑定到 root 是个坏主意吗?
如果是这样,我如何将它单独绑定到每个小部件并避免重复打印任何没有空的东西 event.char?
#!/usr/bin/env python
#sample.py
import tkinter as tk
def set_key(event):
print(f"Key: '{event.char}', '{event.keysym}'")
focus = root.focus_get()
focus.delete(0, tk.END)
if (event.char.split() != []):
focus.insert(0, event.char)
else:
focus.insert(0, event.keysym)
root = tk.Tk()
root.option_add("*Font", "24")
keys = ["1", "2", "3", "4", "q", "w", "e", "r", "a", "s", "d", "f", "z", "x", "c", "v"]
keyboard_entries = []
for idx in range(16):
keyboard_entries.append(tk.Entry(root, width=7))
keyboard_entries[idx].grid(row=(idx//4), column=(idx%4))
keyboard_entries[idx].insert(0, keys[idx])
#keyboard_entries[idx].bind("<Key>", set_key) #Problematic
root.bind("<Key>", set_key) #Not problematic
root.mainloop()
Results when binding to root
Results when binding to each Entry
Considering my actual program has a few buttons and a canvas, is it a bad idea to bind to root?
是的,这是个坏主意。绑定到 root 意味着每个小部件都会受到影响。
If so, how can I bind it to each widget individually and avoid double printing anything without an empty event.char
好吧,您总是可以单独绑定到每个小部件。看起来您已经尝试过了,但不清楚为什么您认为它不起作用。
keyboard_entries[idx].bind("<Key>", set_key)
至于如何不获取双字符,问题是在调用绑定函数后会发生对键的默认绑定。最简单的解决方案是通过从您的函数返回 "break" 来防止触发原始绑定。
此外,您不需要在函数中获取焦点,因为 event
对象的一部分是对接收事件的小部件的引用。
def set_key(event):
event.widget.delete(0, "end")
if (event.char.split() != []):
event.widget.insert(0, event.char)
else:
event.widget.insert(0, event.keysym)
return "break"
有关事件和绑定的详细说明,请参阅此答案:
我有一系列 16 个 Tk Entry 小部件,我想将
如果我将
考虑到我的实际程序有几个按钮和一个 canvas,将
如果是这样,我如何将它单独绑定到每个小部件并避免重复打印任何没有空的东西 event.char?
#!/usr/bin/env python
#sample.py
import tkinter as tk
def set_key(event):
print(f"Key: '{event.char}', '{event.keysym}'")
focus = root.focus_get()
focus.delete(0, tk.END)
if (event.char.split() != []):
focus.insert(0, event.char)
else:
focus.insert(0, event.keysym)
root = tk.Tk()
root.option_add("*Font", "24")
keys = ["1", "2", "3", "4", "q", "w", "e", "r", "a", "s", "d", "f", "z", "x", "c", "v"]
keyboard_entries = []
for idx in range(16):
keyboard_entries.append(tk.Entry(root, width=7))
keyboard_entries[idx].grid(row=(idx//4), column=(idx%4))
keyboard_entries[idx].insert(0, keys[idx])
#keyboard_entries[idx].bind("<Key>", set_key) #Problematic
root.bind("<Key>", set_key) #Not problematic
root.mainloop()
Results when binding to root
Results when binding to each Entry
Considering my actual program has a few buttons and a canvas, is it a bad idea to bind to root?
是的,这是个坏主意。绑定到 root 意味着每个小部件都会受到影响。
If so, how can I bind it to each widget individually and avoid double printing anything without an empty event.char
好吧,您总是可以单独绑定到每个小部件。看起来您已经尝试过了,但不清楚为什么您认为它不起作用。
keyboard_entries[idx].bind("<Key>", set_key)
至于如何不获取双字符,问题是在调用绑定函数后会发生对键的默认绑定。最简单的解决方案是通过从您的函数返回 "break" 来防止触发原始绑定。
此外,您不需要在函数中获取焦点,因为 event
对象的一部分是对接收事件的小部件的引用。
def set_key(event):
event.widget.delete(0, "end")
if (event.char.split() != []):
event.widget.insert(0, event.char)
else:
event.widget.insert(0, event.keysym)
return "break"
有关事件和绑定的详细说明,请参阅此答案: