有没有办法将关键事件映射到其他字母。这是一种将密码放入输入字段的便捷方式:
一个例子:我的笔记本电脑键盘上没有额外的密码键,但我经常需要输入数字。所以我认为有一个条目可以改变密码中的字母会很好:
e -> 1
z -> 2
d -> 3
v -> 4
f -> 5
...
我尝试了很多事情:
- 标签模拟条目,但事件存在问题,因为标签小部件不支持此事件。
- 通过条目
<Key>事件,我无法更改条目中的输入。按下的e将始终显示在条目中。(我使用了 tkinter 的传播验证方法!)。
您尝试绑定<Key>失败的原因可能是因为您return "break"在处理击键后没有做。
您可以为键盘上的任何键创建自己的绑定。例如,要更改“e”以执行任何您想要的操作,请执行self.entry.bind("<e>", ...). 然后,在绑定中,您可以插入任何您想要的内容。如果你这样做return "break",那么密钥的默认处理将被禁止。
如果要在字典中设置映射,可以绑定到"<Key>". 这是一个简单的例子:
import Tkinter as tk
class Example(tk.Frame):
map = {"e": "1",
"z": "2",
"v": "3",
# ... and so on
}
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.entry = tk.Entry(self, width=20)
self.entry.pack(side="top", fill="x")
self.entry.bind("<Key>", self.keymap)
def keymap(self, event):
if event.char in self.map:
self.entry.insert("insert", self.map[event.char])
return "break"
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(side="top", fill="both", expand=True)
root.mainloop()
好吧我自己的解决方案...
感谢@Justin S Barrett 和@Brian Oakley。
根据@Brian Oakley 的提示,我解决了我的问题:
class DigitEntry(Frame):
mapping = {
"o": "0",
"e": "1",
"z": "2",
"d": "3",
"v": "4",
"f": "5",
"s": "6",
"i": "7",
"a": "8",
"n": "9",
",": ".",
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7",
"8": "8",
"9": "9",
".": "."
}
def __init__(self, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
self.entry = Entry(self, width=10)
self.entry.pack(fill="x")
self.entry.bind("<Key>", self.keymap)
self.entry.bind("<FocusOut>", self.check)
def check(self, event):
"""if checks are necessary
"""
pass
def keymap(self, event):
""" do mappings, pass allowed inputs and block the rest.
"""
if event.char in self.mapping:
self.entry.insert("insert", self.mapping[event.char])
return "break"
elif event.keysym in ["BackSpace", "Tab"]:
pass
else:
self.entry.insert("insert", "")
return "break"
class PointsEntry(DigitEntry):
def __init__(self, *args, **kwargs):
DigitEntry.__init__(self, *args, **kwargs)
def check(self, event):
value = self.entry.get()
if value.find(".") >= 0:
if not (value[-1] == "." or value[-2:] == ".5"):
err = value + " bad frac digit"
self.entry.delete(0, "end")
self.entry["bg"] = "red"
self.entry.insert("insert", err)
elif value[-1] == ".":
self.entry.insert("insert", "5")
if len(value) == 1:
self.entry.insert(0, "0")
return "break"
我知道的最简单的方法是使用您分配给条目小部件的字符串变量来拦截输入。您可以对此类变量执行的一件事是在该变量更改时执行一个函数或方法,并且您可以使用该函数/方法来修改条目内容。这是一个简单的例子:
from Tkinter import *
class EntryHack(Frame):
def __init__(self, root):
self.root = root
Frame.__init__(self, root)
self.pack(side="left")
self.entry = Entry(self, width=10)
self.entry.pack(side="left")
self.entry_var = StringVar()
self.entry_var.trace_variable("w", self.changed)
self.entry["textvariable"] = self.entry_var
def changed(self, *args):
"""Intercept changes"""
value = self.entry_var.get()
changed = False
frm = "zxcasdqwe"
to = "123456789"
if not value.isdigit():
changed = True
new = ""
for char in value:
if char.isdigit() or char not in frm:
new += char
else:
new += to[frm.index(char)]
value = new
if changed:
self.entry_var.set(value)
root = Tk()
app = EntryHack(root)
root.mainloop()
赋值的好处是,当你在字段中输入内容时trace_variable,你给它的函数/方法将被调用,但在你手动更改变量时不会被调用,从而避免了无限循环。