Tkinter 输入框,不允许一次输入和显示一个字符串

Tkinter entrybox, not allowing typing and showing one string at a time

我正在尝试制作一个输入框,当它获得焦点时获取键盘输入,并且只在框的中间显示该键名称,没有 blinking 栏并且不允许编辑。并且还将变量更改为键。

所以如果 [ ] 是一个输入框。我输入 F7 然后框应该显示 [ F7 ],然后当我按下退格键时框应该显示 [ Backspace ].

在我的代码中,F1F2 等特殊键甚至没有给我正确的反馈,所有功能键都返回 '''\x08' 为退格键。如果所有的键都显示不同的字符,我想我可以找到一种方法来 link 我想要打印的字符和名称。但这种情况并非如此。而输入框类型 [1234| ] 不像 [ 1 ]。而且我不知道如何在输入框中获取键名。

    def callback(event):
        key_input_entered.focus_set()
        print(repr(event.char))

    kb_frame = ttk.Frame(self.kb)
    kb_frame.grid(column=0, row=1, pady=(7, 19))
    ttk.Label(kb_frame, text='Enter Key').grid(column=0, row=0, pady=4)
    key_input = tk.StringVar()
    key_input_entered = ttk.Entry(kb_frame, width=15, textvariable=key_input)
    key_input_entered.grid(column=0, row=1)
    key_input_entered.bind('<Key>', callback)

要获得 Entry 小部件中的所有功能,您需要对其进行修改。

  1. Entry 小部件中取消绑定序列 <Key><BackSpace>

  2. 通过配置 justify='center' 使文本居中对齐。

  3. 要获得所需的键名,您必须将 <Key> 绑定到 Entry 小部件并获得 event.keysym,因为它会为您提供键名按下.

  4. 如果您不想看到 insertEntry 小部件中闪烁,您可以尝试 insertwidth=0 但对我来说它不起作用知道为什么,所以我在 'readonly' 和 'normal' 状态之间切换,就像在函数 self._display(..) 中一样,当 Entry 小部件处于 'readonly' 状态时它没有允许任何文本插入。

这是继承自 Entry 的自定义 class Entry_Box 小部件。

import tkinter as tk

class EntryBox(tk.Entry):
    def __init__(self, master=None, cnf={}, **kw):
        kw = tk._cnfmerge( (kw, cnf) )
        kw['justify'] = kw.get('justify', 'center')
        kw['state'] = 'readonly' 
        super(EntryBox, self).__init__(master=master, **kw)
        self.bind_class(self, '<Key>', self._display)

    def _display(self, evt):
        self['state'] = 'normal'
        self.delete('0', 'end')
        self.insert('0', str(evt.keysym))
        self['state'] = 'readonly'


if __name__ == "__main__":
    root = tk.Tk()
    EntryBox().pack()
    root.mainloop()

代码简单解释:

tk._cnfmerge()是tkinter库的一个内部函数,这个函数的目的是将多个字典组合在一起。现在你可能想知道我们可以在没有这个功能的情况下组合字典。是的,我们可以,但是这样我们就不会得到任何错误,比如任何字典是 None。这是函数的 source code

bind_class 就像 bind 函数,但它指的是内部 class 名称,例如 Entry 小部件具有类似于 <Key>, <BackSpace>, <Return>, ... 的绑定是内部绑定,因此如果用户尝试绑定或取消绑定任何序列,它不会干扰内部绑定,直到他们使用具有相同 className 的 unbind_class(className 就像标签)内部给出。这个可以更好的解释。