Supongamos que tengo lo siguiente Buttonhecho con Tkinter en Python:
import Tkinter as Tk
win = Tk.Toplevel()
frame = Tk.Frame(master=win).grid(row=1, column=1)
button = Tk.Button(master=frame, text='press', command=action)
Se actionllama al método cuando presiono el botón, pero ¿y si quisiera pasar algunos argumentos al método action?
He intentado con el siguiente código:
button = Tk.Button(master=frame, text='press', command=action(someNumber))
Esto solo invoca el método inmediatamente, y presionar el botón no hace nada.

Respuestas:
Personalmente prefiero usarlo
lambdasen tal escenario, porque en mi opinión es más claro y simple y tampoco te obliga a escribir muchos métodos de envoltura si no tienes control sobre el método llamado, pero eso es ciertamente una cuestión de gustos.Así es como lo haría con un lambda (tenga en cuenta que también hay alguna implementación de curry en el módulo funcional, por lo que también puede usar eso):
fuente
partialfunciona en este caso."This just invokes the method immediately, and pressing the button does nothing"sucede la declaración de OP ?callback=lambda x=x: f(x)como enfs = [lambda x=x: x*2 for x in range(5)] ; print [f() for f in fs]Esto también se puede hacer mediante el uso
partialde functools de biblioteca estándar , como este:fuente
button = Tk.Button(master=frame, text='press', command=partial(action, arg))action_with_args = partial(action, arg1, arg2... argN)GUI de ejemplo:
Digamos que tengo la GUI:
¿Qué sucede cuando se presiona un botón?
Observe que cuando
btnse presiona llama a su propia función, que es muy similar abutton_press_handlela del siguiente ejemplo:con:
Simplemente puede pensar que esa
commandopción debe establecerse como, la referencia al método que queremos llamar, similar acallbackinbutton_press_handle.Llamar a un método ( devolución de llamada ) cuando se presiona el botón
Sin argumentos
Entonces, si quería
printalgo cuando se presiona el botón, necesitaría configurar:Preste mucha atención a la falta de
()unprintmétodo que se omite en el sentido de que: "Este es el nombre del método al que quiero que llame cuando lo presione, pero no lo llame en este mismo instante". Sin embargo, no pasé ningún argumento para el,printpor lo que imprimió lo que imprime cuando se lo llamó sin argumentos.Con argumento (s)
Ahora, si también quisiera pasar argumentos al método que quiero que me llamen cuando se presiona el botón, podría hacer uso de las funciones anónimas, que se pueden crear con la declaración lambda , en este caso para el
printmétodo incorporado, como el siguiente :Llamar a varios métodos cuando se presiona el botón
Sin argumentos
También puede lograrlo usando la
lambdadeclaración, pero se considera una mala práctica y, por lo tanto, no la incluiré aquí. La buena práctica es definir un método separadomultiple_methodsque llame a los métodos deseados y luego configurarlo como la devolución de llamada al presionar el botón:Con argumento (s)
Para pasar argumentos al método que llama a otros métodos, nuevamente use la
lambdadeclaración, pero primero:y luego establecer:
Devolver objeto (s) de la devolución de llamada
También tenga en cuenta que
callbackno puede realmentereturnporque solo se llama dentrobutton_press_handleconcallback()en lugar dereturn callback(). Lo hace,returnpero no en cualquier lugar fuera de esa función. Por lo tanto, debería modificar los objetos a los que se puede acceder en el ámbito actual.Ejemplo completo con modificaciones de objeto globales
El siguiente ejemplo llamará a un método que cambia
btnel texto de cada vez que se presiona el botón:Espejo
fuente
La capacidad de Python para proporcionar valores predeterminados para argumentos de función nos da una salida.
Ver: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html
Para más botones, puede crear una función que devuelva una función:
fuente
myXymyYfunciona perfectamente muchas gracias.Sobre la base de la respuesta de Matt Thompson: una clase se puede hacer invocable para que se pueda usar en lugar de una función:
fuente
La razón por la que invoca el método inmediatamente y al presionar el botón no hace nada es que
action(somenumber)se evalúa y su valor de retorno se atribuye como el comando para el botón. Entonces, siactionimprime algo para decirle que se ha ejecutado y regresaNone, solo ejecutaactionpara evaluar su valor de retorno y se le daNonecomo el comando para el botón.Para tener botones para llamar a funciones con diferentes argumentos, puede usar variables globales, aunque no puedo recomendarlo:
Lo que haría es hacer un
classobjeto cuyos objetos contendrían todas las variables requeridas y métodos para cambiarlos según sea necesario:fuente
Creo que debería arreglar esto
fuente
Lo mejor que puede hacer es usar lambda de la siguiente manera:
fuente
Llego extremadamente tarde, pero aquí hay una manera muy simple de lograrlo.
Simplemente envuelva la función que desea usar en otra función y llame a la segunda función al presionar el botón.
fuente
var1yvar2en el módulo principal, puede omitirfunction1y poner unaprintdeclaraciónfunction2. ¿Se refiere a otras situaciones que no entiendo?Las lambdas están muy bien, pero también puedes probar esto (que funciona en un bucle for por cierto):
Esto funciona porque cuando se establece el enlace, una pulsación de tecla pasa el evento como argumento. A continuación, puede llamar los atributos fuera del evento como
event.charobtener "1" o "UP" ect. Si necesita un argumento o varios argumentos distintos de los atributos del evento. solo crea un diccionario para almacenarlos.fuente
También he encontrado este problema antes. Puedes usar lambda:
fuente
Use una lambda para pasar los datos de entrada a la función de comando si tiene más acciones para llevar a cabo, de esta manera (he intentado hacerlo genérico, así que solo adapte):
Esto pasará la información en el evento a la función del botón. Puede haber más formas pitonescas de escribir esto, pero funciona para mí.
fuente
JasonPy - algunas cosas ...
Si coloca un botón en un bucle, se creará una y otra vez ... lo que probablemente no sea lo que desea. (tal vez lo es) ...
La razón por la que siempre obtiene el último índice son los eventos lambda que se ejecutan cuando hace clic en ellos, no cuando se inicia el programa. No estoy seguro al 100% de lo que está haciendo, pero tal vez intente almacenar el valor cuando esté hecho y luego llámelo más tarde con el botón lambda.
por ejemplo: (no use este código, solo un ejemplo)
entonces puedes decir ...
¡espero que esto ayude!
fuente
Una forma sencilla sería configurar
buttonconlambdala siguiente sintaxis:fuente
Para la posteridad: también puedes usar clases para lograr algo similar. Por ejemplo:
El botón puede ser creado simplemente por:
Este enfoque también le permite cambiar los argumentos de la función, es decir, estableciendo
instance1.x = 3.fuente
Necesitas usar
lambda:fuente
Utilizar lambda
salida:
fuente