Ottieni un gestore eventi associato in Tkinter
-
02-07-2019 - |
Domanda
Dopo aver associato un metodo a un evento di un elemento Tkinter c'è un modo per riavere il metodo?
>>> 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.???
Soluzione
La chiamata associata a farlo per l'API tk C sarebbe Get_GetCommandInfo quale
inserisce informazioni sul comando nella struttura Tcl_CmdInfo appuntita a da infoPtr
Tuttavia questa funzione non è utilizzata da nessuna parte in _tkinter.c che è l'associazione per tk utilizzata da python trough Tkinter.py .
Pertanto è impossibile estrarre la funzione associata da tkinter. Devi ricordare tu stesso quella funzione.
Altri suggerimenti
Il modo standard per farlo in Tcl / Tk è banale: usi lo stesso comando bind ma senza l'argomento finale.
bind .b <Button-1> doSomething
puts "the function is [bind .b <Button-1>]"
=> the function is doSomething
Puoi fare qualcosa di simile con Tkinter ma, sfortunatamente, i risultati non sono così utilizzabili:
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'
Ovviamente, Tkinter sta facendo un sacco di giocoleria sotto le coperte. Una soluzione sarebbe quella di scrivere una piccola procedura di supporto che ricordi questo per te:
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))
Lo useresti in questo modo:
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>")
Quando eseguo il codice precedente ottengo:
before, binding for <Button-1>: None
after, binding for <Button-1>: <function doSomething at 0xb7f2e79c>
Come ultimo avvertimento, non uso molto Tkinter, quindi non sono sicuro di quali siano le conseguenze di aggiungere dinamicamente un attributo a un'istanza di widget. Sembra innocuo, ma in caso contrario puoi sempre creare un dizionario globale per tenere traccia dei collegamenti.
Non sembra essere ... perché non salvarlo da soli se ne hai bisogno o utilizzare una funzione non anonima?
Inoltre, il tuo codice non funziona come scritto: le funzioni lambda
possono contenere solo espressioni, non istruzioni, quindi print
non funziona (questo cambierà in Python 3.0 quando print ()
diventa una funzione).