Tkinter enlazando una función con argumentos a un widget

Tengo un marco tkinter y un botón adjunto:

from tkinter import * def rand_func(a,b,c,effects): print (a+b+c) root=Tk() frame=Frame(root) frame.bind("",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 que se realice la misma función cuando el usuario presiona enter y cuando presiona el botón. Lamentablemente, el código anterior da un error en el enlace de marco. ¿Alguien sabe una solución a este problema?

Cuando crea un enlace con bind , Tkinter agrega automáticamente un argumento que contiene información sobre el evento. Tendrás que rand_func en cuenta en tu definición de rand_func o en cómo lo llamas.

Este argumento no se incluye cuando utiliza el atributo de command . Debe tener en cuenta 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 utiliza lambda en el enlace para aceptar el evento adicional solo cuando se usa el comando de bind , pero no se 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("", 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 enfoque del teclado y, a menos que tenga el enfoque, el enlace nunca se activará. Si está configurando un enlace global, debe enlazar a la etiqueta de enlace “todos” (utilizando el método bind_all ) o al widget de nivel superior.

Qué tal si:

 import tkinter as tk def rand_func(eff=None, a=1, b=2, c=3): print(a + b + c) root = tk.Tk() root.bind("", lambda eff: rand_func(eff, a=10, b=20, c=30)) frame = tk.Frame(root) frame.pack() button = tk.Button(frame, text="click me", command=lambda: rand_func(None, 1, 2, 3)) button.pack() root.mainloop()