Obtenir un gestionnaire d'événements lié à Tkinter
-
02-07-2019 - |
Question
Après une liaison d'une méthode à un événement d'un élément Tkinter, existe-t-il un moyen de récupérer la méthode?
>>> root = Tkinter.Tk()
>>> frame = Tkinter.Frame(root, width=100, height=100)
>>> frame.bind('<Button-1>', lambda e: pprint('Click')) # function needed
>>> frame.pack()
>>> bound_event_method = frame.???
La solution
L’appel associé à cette opération pour l’API C de tk serait Get_GetCommandInfo qui
place des informations sur la commande dans la structure Tcl_CmdInfo pointée à par infoPtr
Cependant, cette fonction n'est utilisée nulle part dans _tkinter.c qui est la liaison pour tk utilisée par python via Tkinter.py .
Il est donc impossible d'extraire la fonction liée de tkinter. Vous devez vous rappeler cette fonction vous-même.
Autres conseils
La manière standard de le faire dans Tcl / Tk est simple: vous utilisez la même commande bind, mais sans l'argument final.
bind .b <Button-1> doSomething
puts "the function is [bind .b <Button-1>]"
=> the function is doSomething
Vous pouvez faire quelque chose de similaire avec Tkinter mais les résultats ne sont malheureusement pas tout à fait aussi utilisables:
e1.bind("<Button-1>",doSomething)
e1.bind("<Button-1>")
=> 'if {"[-1208974516doSomething %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y %D]" == "break"} break\n'
De toute évidence, Tkinter jongle beaucoup avec les couvertures. Une solution serait d'écrire une petite procédure d'assistance qui s'en souviendrait pour vous:
def bindWidget(widget,event,func=None):
'''Set or retrieve the binding for an event on a widget'''
if not widget.__dict__.has_key("bindings"): widget.bindings=dict()
if func:
widget.bind(event,func)
widget.bindings[event] = func
else:
return(widget.bindings.setdefault(event,None))
Vous l'utiliseriez comme ceci:
e1=Entry()
print "before, binding for <Button-1>: %s" % bindWidget(e1,"<Button-1>")
bindWidget(e1,"<Button-1>",doSomething)
print " after, binding for <Button-1>: %s" % bindWidget(e1,"<Button-1>")
Lorsque je lance le code ci-dessus, je reçois:
before, binding for <Button-1>: None
after, binding for <Button-1>: <function doSomething at 0xb7f2e79c>
Pour finir, je n’utilise pas beaucoup Tkinter, donc je ne sais pas trop quelles sont les conséquences de l’addition dynamique d’un attribut à une instance de widget. Cela semble inoffensif, mais si vous ne le faites pas, vous pouvez toujours créer un dictionnaire global pour garder la trace des liaisons.
Ne semble pas être ... pourquoi ne pas le sauvegarder vous-même si vous en avez besoin, ou utilisez une fonction non anonyme?
De plus, votre code ne fonctionne pas comme il est écrit: les fonctions lambda
ne peuvent contenir que des expressions, pas des instructions. Par conséquent, print
est interdit (cela changera dans Python 3.0 lorsque print ()
devient une fonction).