Поле ввода Tkinter, не позволяющее набирать и показывать по одной строке за раз - PullRequest
2 голосов
/ 04 мая 2019

Я пытаюсь создать поле ввода, которое получает ввод с клавиатуры, когда оно находится в фокусе, и отображать только то имя клавиши в середине поля без мигающей полосы и не разрешать редактирование.А также изменяет переменную на ключ.

То есть, если [ ] - это поле ввода.Я набираю F7, тогда в поле должно отображаться [ F7 ], затем, когда я нажимаю кнопку возврата, поле должно отображать [ Backspace ].

В моем коде специальные клавиши, такие как F1, F2 и т. Д.даже не дают мне правильную обратную связь, возвращая мне '' для всей функциональной клавиши и '\x08' для клавиши возврата.Если бы все клавиши показывали разные символы, я думаю, что я мог бы найти способ связать символы и имена, которые я хочу напечатать.Но это не так.И типы ввода типа [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)

1 Ответ

2 голосов
/ 04 мая 2019

Чтобы получить все функции в виджете Entry, вам нужно изменить его.

  1. Отсоедините последовательность <Key>, а также <BackSpace> из виджета Entry.

  2. Обоснуйте текст для выравнивания по центру, настроив justify='center'.

  3. Чтобы получить желаемое имя клавиши, вам необходимо связать <Key> с виджетом Entry и получить event.keysym, поскольку оно дает вам имя нажатой клавиши.

  4. Если вы не хотите видеть мигание insert в виджете Entry, вы можете попробовать insertwidth=0, но для меня это не работает, не знаю почему, поэтому я переключаюсь между «только для чтения» и «нормальные» состояния, как и в функции self._display(..), когда виджет Entry находится в состоянии «только для чтения», он не допускает вставки текста.

Вот пользовательский класс Entry_Box, унаследованный от виджета Entry.

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 Вот исходный код для функции.

Функция bind_class похожа на функцию bind, но она ссылается на внутреннее имя класса, например, Entry виджет имеет привязки, подобные <Key>, <BackSpace>, <Return>, ..., которые являются внутренними привязками, поэтому, если пользователь пытается связать или отменить привязку любого последовательность не будет мешать внутренним связываниям, пока они не будут использовать unbind_class с тем же именем className (className похоже на тег), заданным внутри. Этот пост может объяснить лучше.

...