Я хочу связать себя с событиями после Text
привязок класса виджета, чтобы изменить текст виджета, когда вызывается моя функция привязки. Мое связывание, например self.text.bind("<Key>", self.callback)
, вызывается до изменения содержимого в виджетах.
Как связать собственные события в текстовом виджете Tkinter после того, как он будет привязан текстовым виджетами?
Ответ 1
Что происходит в вашем случае, так это то, что привязка для печати значения происходит до привязки класса, и это привязка класса, которая фактически берет ввод пользователя и помещает его в виджет. Существует несколько способов решения этой проблемы. Вы можете привязываться к <KeyRelease>
вместо <KeyPress>
, или вы можете использовать встроенные функции проверки входа, чтобы ваш код вызывался при каждом нажатии клавиши. С помощью этого решения вам будут предоставлены все необходимые данные - значение перед изменением, значение после изменения, нажатый ключ и т.д.
Другой выбор - изменить порядок обработки событий. Поскольку ваш вопрос специально спросил, как изменить порядок, вот что я буду решать.
Несмотря на то, что привязка, похоже, связана с виджетами, когда вы делаете что-то вроде entry.bind(...)
, вы фактически назначаете привязку к тегу привязки (или "bindtag" ). По умолчанию каждый виджет имеет привязку, которая совпадает с именем виджета. Другие bindtags включают класс виджета (например, "Enter" ), путь к корневому окну (например: "." ) И специальный тег "все". Виджетам присваивается набор bindtags, которые обрабатываются в том случае, когда получено событие. Порядок по умолчанию идет от большей части к наименее специфичной: widget, class, toplevel, all.
Существует несколько способов манипулирования привязными элементами, чтобы получить желаемый результат. Один из вариантов состоит в том, чтобы изменить порядок привязок. Перемещая bindtag, представляющий виджет, который будет после bindtag, представляющий класс, класс обработает событие, прежде чем передать его конкретному виджету.
Другой выбор - добавить дополнительный привязку, которая после привязки класса, а затем привязать привязки к этому тегу, а не к тегу, который представляет виджет.
Зачем выбирать один за другим? Переупорядочивая порядок, вы будете влиять на все привязки к этому виджету. Если у вас много привязок, а некоторые зависят от порядка (чтобы, например, запретить некоторые нажатия клавиш), изменение порядка может привести к прекращению работы этих привязок.
Введя новый bindtag, вы можете выбрать, какие привязки произойдут до привязки классов и которые произойдут после.
В следующем коде я создаю три виджета ввода. Первый использует набор привязок по умолчанию (явно заданный в примере, хотя они идентичны по умолчанию). Второй изменяет порядок, а третий вводит дополнительный bindtag. Запустите код, затем нажмите клавишу, когда фокус находится в каждом окне. Обратите внимание, что в первом виджетах записи привязка всегда кажется одним символом. Опять же, это связано с тем, что привязка виджета происходит до того, как привязка класса помещает символ в виджет.
Во втором и третьем примерах привязка происходит после привязки класса, поэтому функция видит изменения в виджетах.
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")
# Three different bindtags. The first is just the default but I'm
# including it for illustrative purposes. The second reverses the
# order of the first two tags. The third introduces a new tag after
# the class tag.
entry1.bindtags(('.entry1', 'Entry', '.', 'all'))
entry2.bindtags(('Entry', '.entry2', '.', 'all'))
entry3.bindtags(('.entry3','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")
# normally you bind to the widget; in the third case we're binding
# to the new bindtag we've created
entry1.bind("<KeyPress>", OnKeyPress)
entry2.bind("<KeyPress>", OnKeyPress)
entry3.bind_class("post-class-bindings", "<KeyPress>", OnKeyPress)
root.mainloop()