Подтвердить что ты не робот

Как получить обратный вызов события при изменении виджета Tkinter Entry?

Именно в этом вопросе говорится. Text виджеты имеют событие <<Modified>>, но Entry виджетов не отображается.

4b9b3361

Ответ 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-й из них может фактически потерять фокус!)