Solución:
Agregue un Tkinter StringVar a su widget de entrada. Vincula tu devolución de llamada a StringVar usando el método de seguimiento.
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()
En el momento de escribir este artículo (2017, Python 3.6, tkinter versión 8.6.6), los documentos sugieren que .trace
es obsoleto. La forma sugerida ahora parece ser:
sv.trace_add("write", callback)
Esto funciona muy bien si desea recibir una notificación cada vez que se cambia la variable. Sin embargo, mi aplicación solo quiere una notificación cuando el usuario termine de editar el texto. Descubrí que el mecanismo de “validación” funciona bien aquí:
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()
Esto invocará callback
cada vez que el widget de entrada pierde el foco (¡agregué un widget de segunda entrada para que el primero pueda perder el foco!)
¡Gracias Steven! Tkinter Folklore de Russell Owen explica cómo obtener el valor StringVar directamente del argumento del nombre (PY_VAR #) usando globalgetvar (), pero no cómo asignar el nombre a un widget. Su método lambda para cambiar los argumentos de devolución de llamada es como magia (para nosotros, los novatos de Python, al menos).
Cuando hay más de una entrada, a menudo es necesario saber no solo el valor, sino también qué entrada se modificó. Ampliando ligeramente el ejemplo de Steven, el siguiente (Python3) pasa un índice que se puede usar para realizar un seguimiento de múltiples entradas.
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.string_vars = []
self.fruit = ("Apple", "Banana", "Cherry", "Date")
for f in self.fruit:
i = len(self.string_vars)
self.string_vars.append(StringVar())
self.string_vars[i].trace("w", lambda name, index, mode, var=self.string_vars[i], i=i:
self.entryupdate(var, i))
Label(cf, text=f).grid(column=2, row=i)
Entry(cf, width=6, textvariable=self.string_vars[i]).grid(column=4, row=i)
root = Tk()
root.title("EntryUpdate")
app = Fruitlist(root)
root.mainloop()