2011-09-04 73 views
6

tengo un marco tkinter y un botón que se le atribuye:Tkinter vinculante una función con argumentos a un widget

from tkinter import * 

def rand_func(a,b,c,effects): 
    print (a+b+c) 

root=Tk() 
frame=Frame(root) 
frame.bind("<Return>",lambda a=10, b=20, c=30: rand_func(a,b,c)) 
frame.pack() 

button=Button(frame, text="click me", command=lambda a=1,b=2,c=3,eff=None:rand_func(a,b,c)) 
button.pack() 

root.mainloop() 

Quiero la misma función que se realiza cuando el usuario pulsa entrar y cuando se presiona el botón. Lamentablemente, el código anterior da un error en el enlace del marco. ¿Alguien sabe una solución a este problema?

Respuesta

12

Cuando se crea una unión con bind, Tkinter añade automáticamente un argumento que tiene información sobre el evento. Tendrá que dar cuenta de eso en su definición rand_func o en cómo lo llame.

Este argumento es no incluido cuando utiliza el atributo command. Debe tener cuidado de dar cuenta de este argumento adicional, ya sea en cómo llama a la función en cada caso o en cómo la función interpreta sus parámetros.

Aquí hay una solución que usa lambda en el enlace para aceptar el evento adicional solo cuando se usa el comando bind, pero no lo pasa al comando final.

import tkinter as tk 

class SampleApp(tk.Tk): 
    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 
     self.frame = tk.Frame(self) 
     self.frame.pack() 
     self.button = tk.Button(self.frame, text="click me", 
          command=lambda a=1, b=2, c=3: 
           self.rand_func(a, b, c)) 
     self.button.pack() 
     self.frame.bind("<Return>", 
         lambda event, a=10, b=20, c=30: 
          self.rand_func(a, b, c)) 
     # make sure the frame has focus so the binding will work 
     self.frame.focus_set() 

    def rand_func(self, a, b, c): 
     print "self:", self, "a:", a, "b:", b, "c:", c 
     print (a+b+c) 

app = SampleApp() 
app.mainloop() 

Dicho esto, es raro que la unión a un marco sea lo correcto. Por lo general, un cuadro no tendrá el foco del teclado y, a menos que tenga foco, el enlace nunca se disparará. Si está configurando un enlace global, debe vincularse a la etiqueta de enlace "todos" (utilizando el método bind_all) o al widget de nivel superior.

+0

Muchas gracias, ya que sugirió que bind_all era lo que necesitaba; –

+0

Es importante tener en cuenta que _automáticamente se agrega un argumento que tiene información sobre el evento_ se aplica solo a las devoluciones de llamada vinculadas por el método 'bind'. Aquellos vinculados con la opción 'command' (en constructor o con' configure() ') no reciben dicho objeto de evento. Esta distinción no es fácil de detectar en los documentos (al menos no he encontrado ninguna), pero aquí está [confirmación] (https://stackoverflow.com/questions/36726716/what-is-the-difference-between- command-and-bind-in-tkinter) –

+1

@ o'rety: He actualizado la respuesta para abordar sus inquietudes. –

1

¿Qué tal:

from Tkinter import * 

def rand_func(eff=None,a=1,b=2,c=3): 
    print (a+b+c) 

root=Tk() 
root.bind("<Return>",lambda eff:rand_func(eff,a=10,b=20,c=30)) 

frame=Frame(root) 
frame.pack() 

button=Button(frame, text="click me", command=lambda:rand_func(None,1,2,3)) 
button.pack() 

root.mainloop() 
+0

Olvidé escribir en el código que los argumentos son diferentes, pregunta de edición –

Cuestiones relacionadas