Вопрос-Ответ

Basic query regarding bindtags in tkinter

Базовый запрос относительно bindtags в tkinter

В приведенном примере из этого поста упоминалось, что если используются биндтеги по умолчанию, то значение события не будет видно внутри определения (будет задержка на единицу).

Было дано некоторое объяснение относительно привязки к классу.
Я новичок, поэтому хотел бы понять подробную причину.
Может кто-нибудь, пожалуйста, объяснить, почему это не работало в первом случае и работало во втором (когда порядок bindtags изменен).

import Tkinter

def OnKeyPress(event):
value = event.widget.get()
string="value of %s is '%s'" % (event.widget._name, value)
status.configure(text=string)

root = Tkinter.Tk()

entry1 = Tkinter.Entry(root, name="entry1")
entry2 = Tkinter.Entry(root, name="entry2")
entry3 = Tkinter.Entry(root, name="entry3")

entry1.bindtags(('.entry1', 'Entry', '.', 'all'))
entry2.bindtags(('Entry', '.entry1', '.', 'all'))
entry3.bindtags(('.entry1','Entry','post-class-bindings', '.', 'all'))

btlabel1 = Tkinter.Label(text="bindtags: %s" % " ".join(entry1.bindtags()))
btlabel2 = Tkinter.Label(text="bindtags: %s" % " ".join(entry2.bindtags()))
btlabel3 = Tkinter.Label(text="bindtags: %s" % " ".join(entry3.bindtags()))
status = Tkinter.Label(anchor="w")

entry1.grid(row=0,column=0)
btlabel1.grid(row=0,column=1, padx=10, sticky="w")
entry2.grid(row=1,column=0)
btlabel2.grid(row=1,column=1, padx=10, sticky="w")
entry3.grid(row=2,column=0)
btlabel3.grid(row=2,column=1, padx=10)
status.grid(row=3, columnspan=2, sticky="w")
entry1.bind("<KeyPress>", OnKeyPress)
entry2.bind("<KeyPress>", OnKeyPress)
entry3.bind_class("post-class-bindings", "<KeyPress>", OnKeyPress)

root.mainloop()
Переведено автоматически
Ответ 1

Когда вы выполняете привязку к виджету, вы на самом деле не привязываетесь к виджету как таковому. Когда вы выполняете mywidget.bind(...), на самом деле происходит то, что привязка связана с тегом bind с тем же именем, что и у виджета.

При обнаружении события Tkinter сначала определяет, какой виджет перехватил событие. У этого виджета будет список из нуля или более (по умолчанию: четырех) связанных с ним тегов bind. Tkinter проверит каждый тег, чтобы увидеть, есть ли привязка, соответствующая событию. Если он найдет один, он выполнит привязку, а затем перейдет к следующему тегу, пока не закончатся теги или одна из связанных функций не вернет строку "break".

Последовательность выглядит примерно так:


  1. Вы нажимаете клавишу "x". На этом этапе "x" нигде не был вставлен

  2. Tkinter получает теги привязки для виджета, который имеет фокус клавиатуры.

  3. По умолчанию первым тегом привязки является сам виджет. Есть ли привязка к этому тегу? Если да, выполните его. Например, вы можете распечатать содержимое виджета. Поскольку другие привязки еще не запущены, "x" не будет частью содержимого.

  4. Если связанная функция возвращает результат "break", обработка событий больше не выполняется. "X" не будет вставлен в виджет.

  5. Если виджет не вернул результат "break", tkinter переходит к следующему тегу привязки.

  6. По умолчанию следующим тегом привязки является класс widget. Существует ли привязка к классу, соответствующая этому событию (нажатию буквы "x")?

  7. В этом случае у класса действительно есть привязка для этого события, которая заключается в фактической вставке "x" в виджет. До этого момента "x" все еще не был вставлен в виджет. Однако после этой привязки, если вы распечатаете содержимое, вы увидите "x"

  8. Обработка продолжается таким образом до тех пор, пока не будут обработаны все теги привязки.

Судя по продолжающемуся обсуждению в разделе комментариев, похоже, что это все еще неясно. Я постараюсь сделать это как можно проще:

Это привязка класса, которая копирует символ из объекта события в памяти в виджет и, таким образом, вызывает его отображение на экране. До срабатывания привязки класса символ не будет отображаться в виджете. После привязки класса он будет в виджете.

python tkinter