Exactement comme le dit la question. Les widgets Text
ont l'événement <>
, mais les widgets Entry
ne semblent pas l'avoir.
@Nicholas: L'échantillon de code fonctionne tel quel. Qu'est-ce que tu trouves qui manque?
Exactement comme le dit la question. Les widgets Text
ont l'événement <>
, mais les widgets Entry
ne semblent pas l'avoir.
Ajoutez un StringVar Tkinter à votre widget Entry. Liez votre fonction de rappel au StringVar en utilisant la méthode de traçage.
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()
J'ai essayé votre solution dans mon code qui a une structure auto, puisque j'ai besoin de changer les propriétés de certains widgets, mais je n'ai pas pu transmettre la structure auto à la trace. Ainsi, j'ai besoin d'utiliser la méthode 'bind' et la balise pour appeler la méthode avec la structure 'self'
@ArtOfWarfare: Vous avez tort. Copiez-collez le code dans un interpréteur Python 2.7 (print
et Tkinter
import doivent être modifiés pour Python 3 ; le lambda resterait le même). Vous verrez que le code s'exécute comme prévu. L'expression lambda est analogue à def anonymous(name, index, mode, sv=sv):return callback(sv)
sauf que c'est une expression, pas une déclaration. StringVar.trace
appelle son rappel avec des arguments inutiles (name, index, mode) que nous ignorons et au lieu de cela, nous créons une fermeture sur le StringVar
lui-même (sv
) que nous utilisons ensuite dans le rappel.
Au moment de l'écriture (2017, Python 3.6, tkinter version 8.6.6) les documents suggèrent que .trace
est obsolète. Forme suggérée maintenant semble être:
sv.trace_add("write", callback)
Cela fonctionne très bien si vous souhaitez être notifié à chaque fois que la variable est modifiée. Cependant, mon application souhaite juste être notifiée lorsque l'utilisateur a fini d'éditer le texte. J'ai trouvé que profiter du mécanisme de "validation" fonctionne bien ici:
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()
Ceci invoquera callback
à chaque fois que le widget d'entrée perd le focus (j'ai ajouté un 2ème widget d'entrée pour que le 1er puisse réellement perdre le focus!)
Merci Steven! Le folklore de Tkinter de Russell Owen explique comment obtenir la valeur de StringVar directement à partir de l'argument name (PY_VAR#) en utilisant globalgetvar(), mais pas comment mapper le nom à un widget. Votre méthode lambda pour changer les arguments de rappel est comme de la magie (pour nous les nouveaux venus en Python, du moins).
Lorsqu'il y a plus d'une Entry, il est souvent nécessaire de savoir non seulement la valeur, mais quelle Entry a été modifiée. En reprenant légèrement l'exemple de Steven, le code suivant (Python3) passe un indice qui peut être utilisé pour suivre plusieurs Entries.
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()
Vous pouvez également utiliser l'événement KeyRelease qui sera déclenché à chaque fois que l'utilisateur clique sur le widget.
Vous pouvez ensuite filtrer les modifications.
from tkinter import *
from tkinter import ttk
class GUI():
def __init__(self):
self.root = Tk()
self.sv = StringVar()
self.prevlaue=''
#entry
self.entry = ttk.Entry(self.root, width=30, textvariable =self.sv)
self.entry.grid(pady=20,padx=20)
self.entry.bind("", self.OnEntryClick) #keyup
self.root.mainloop()
def OnEntryClick(self, event):
value=self.sv.get().strip()
changed = True if self.prevlaue != value else False
print(value, 'Le texte a-t-il changé ? {}'.format(changed))
self.prevlaue = value
#créer l'interface graphique
GUI()
J'espère que cela vous aidera.
J'ai pu faire ce dont j'avais besoin en utilisant l'événement . Voici un exemple:
import tkinter
from tkinter import ttk
def doSomething(event):
text = event.widget.get()
print(text)
window = tkinter.Tk()
testEntry = ttk.Entry(window)
testEntry.bind('', doSomething)
testEntry.grid(column=0,row=0)
thingEntry = ttk.Entry(window)
thingEntry.bind('', doSomething)
thingEntry.grid(column=0,row=1)
startButton = ttk.Button(window,text='OK',command=lambda: print('click'))
startButton.grid(column=0,row=2, sticky='W')
window.mainloop()
print('Au revoir')
La partie importante est:
def doSomething(event):
text = event.widget.get()
print(text)
testEntry.bind('', doSomething)
En utilisant Entry.bind(event,function)
vous pouvez attacher un écouteur d'événements, dans ce cas la fonction doSomething
. Cette fonction reçoit un paramètre, un objet Event
. Vous pouvez ensuite lire ce qui se trouve dans le widget Entry
en utilisant event.widget.get()
.
Chaque fois que vous quittez un Entry
, sa valeur est imprimée. Cela inclut lorsque vous cliquez sur le bouton. Comme vous le verrez dans le test, l'événement du bouton est déclenché après l'événement de l'Entry
,
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.