Именно в этом вопросе говорится. Text
виджеты имеют событие <<Modified>>
, но Entry
виджетов не отображается.
Как получить обратный вызов события при изменении виджета Tkinter Entry?
Ответ 1
Добавьте Tkinter StringVar в виджет Entry. Свяжите обратный вызов с StringVar с помощью метода трассировки.
from Tkinter import *
def callback(sv):
print sv.get()
root = Tk()
sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv))
e = Entry(root, textvariable=sv)
e.pack()
root.mainloop()
Ответ 2
Спасибо, Стивен! Russell Owen Tkinter Folklore объясняет, как получить значение StringVar непосредственно из аргумента name (PY_VAR #) с помощью globalgetvar(), но не как сопоставить имя с виджетами. Ваш лямбда-метод изменения аргументов обратного вызова похож на волшебство (для нас, по крайней мере, для новичков Python).
Если есть несколько записей, часто необходимо знать не только значение, но и какую запись была изменена. Несколько расширяя пример Стивена, следующий (Python3) передает индекс, который можно использовать для отслеживания нескольких записей.
from tkinter import Tk, Frame, Label, Entry, StringVar
class fruitlist:
def entryupdate(self, sv, i):
print(sv, i, self.fruit[i], sv.get())
def __init__(self, root):
cf = Frame(root)
cf.pack()
self.sva = []
self.fruit = ("Apple", "Banana", "Cherry", "Date")
for f in self.fruit:
i = len(self.sva)
self.sva.append(StringVar())
self.sva[i].trace("w", lambda name, index, mode, var=self.sva[i], i=i:
self.entryupdate(var, i))
Label(cf, text=f).grid(column=2, row=i)
Entry(cf, width=6, textvariable=self.sva[i]).grid(column=4, row=i)
root = Tk()
root.title("EntryUpdate")
app = fruitlist(root)
root.mainloop()
Ответ 3
На момент написания (2017, Python 3.6, версия tkinter 8.6.6) документы показывают, что .trace
устарел. Предложенная форма теперь выглядит следующим образом:
sv.trace_add("write", callback)
Это работает очень хорошо, если вы хотите получать уведомления при изменении переменной. Однако мое приложение просто хочет получить уведомление, когда пользователь завершит редактирование текста. Я нашел, что поддерживаю механизм "проверки", чтобы хорошо работать здесь:
from tkinter import *
root = Tk()
sv = StringVar()
def callback():
print(sv.get())
return True
e = Entry(root, textvariable=sv, validate="focusout", validatecommand=callback)
e.grid()
e = Entry(root)
e.grid()
root.mainloop()
Это вызовет callback
всякий раз, когда виджет ввода теряет фокус (я добавил виджет 2-й позиции, так что 1-й из них может фактически потерять фокус!)