Как связать собственные события в виджете Tkinter Text после того, как он будет связан текстовым виджетом?

Я хочу связать события self после привязок класса виджета Text , чтобы изменить текст виджет, когда вызывается моя функция привязки. Моя привязка, например self.text.bind ("", self.callback) , вызывается до изменения содержимого в виджете Text.

13
задан Bryan Oakley 8 September 2015 в 14:17
поделиться

1 ответ

В вашем случае происходит то, что ваша привязка для печати значения происходит до привязки класса, и именно привязка класса фактически принимает пользовательский ввод и помещает его в виджет. Есть несколько способов решить эту проблему. Вы можете привязать к вместо , или вы можете использовать встроенные функции проверки ввода, чтобы ваш код вызывался при каждом нажатии клавиши. С помощью этого решения вам будут предоставлены все необходимые данные - значение до изменения, значение после изменения, нажатая клавиша и т. Д.

Другой вариант - изменить порядок, в котором обрабатываются события . Поскольку ваш вопрос конкретно касается того, как изменить порядок, я обращусь именно к нему.

Хотя кажется, что привязка связана с виджетом, когда вы выполняете что-то вроде entry.bind (...) , вы фактически назначаете привязку «тегу привязки» (или « 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()
26
ответ дан 1 December 2019 в 21:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: