w3schools standard libreria library instalar docs python tkinter

libreria - standard library tkinter python



¿Por qué se ejecuta el parámetro de botón "comando" cuando se declara? (5)

Ejemplo de GUI:

Digamos que tengo la GUI:

import tkinter as tk root = tk.Tk() btn = tk.Button(root, text="Press") btn.pack() root.mainloop()

Qué sucede cuando se presiona un botón

Observe que cuando se presiona btn llama a su propia función que es muy similar a button_press_handle en el siguiente ejemplo:

def button_press_handle(callback=None): if callback: callback() # Where exactly the method assigned to btn[''command''] is being callled

con:

button_press_handle(btn[''command''])

Simplemente puede pensar que la opción de command debe establecerse como, la referencia al método que queremos que se llame, similar a la callback de callback en button_press_handle .

Llamar a un método ( Callback ) cuando se presiona el botón

Sin argumentos

Entonces, si quisiera print algo cuando se presione el botón, necesitaría configurar:

btn[''command''] = print # default to print is new line

Preste mucha atención a la falta de () con el método de print que se omite en el sentido de que: "Este es el nombre del método al que quiero llamar cuando lo presiono, pero no lo llamo solo en este mismo instante". Sin embargo, no pasé ningún argumento para la print así que imprimió lo que imprime cuando se lo llama sin argumentos.

Con argumento (s)

Ahora bien, si también quisiera pasar argumentos al método al que quiero llamar cuando se presiona el botón, podría utilizar las funciones anónimas, que se pueden crear con la declaración lambda , en este caso para el método integrado de print , como el siguiendo:

btn[''command''] = lambda arg1="Hello", arg2=" ", arg3="World!" : print(arg1 + arg2 + arg3)

Llamar a métodos múltiples cuando se presiona el botón

Sin argumentos

También puede lograr eso usando la declaración lambda pero se considera mala práctica y por lo tanto no la incluiré aquí. La buena práctica es definir un método separado, multiple_methods , que llame a los métodos deseados y luego establecerlo como la devolución de llamada al botón presionar:

def multiple_methods(): print("Vicariously") # the first inner callback print("I") # another inner callback

Con argumento (s)

Para pasar un argumento (s) al método que llama a otros métodos, nuevamente haga uso de la declaración lambda , pero primero:

def multiple_methods(*args, **kwargs): print(args[0]) # the first inner callback print(kwargs[''opt1'']) # another inner callback

y luego establecer:

btn[''command''] = lambda arg="live", kw="as the" : a_new_method(arg, opt1=kw)

Devolución de objeto (s) desde la devolución de llamada

Además, tenga en cuenta que la callback realidad no puede return ya que solo se button_press_handle dentro de button_press_handle con callback() en lugar de return callback() . Sí return pero no está 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 global objetos

El ejemplo siguiente llamará a un método que cambia el texto de btn cada vez que se presiona el botón:

import tkinter as tk i = 0 def text_mod(): global i, btn # btn can be omitted but not sure if should be txt = ("Vicariously", "I", "live", "as", "the", "whole", "world", "dies") btn[''text''] = txt[i] # the global object that is modified i = (i + 1) % len(txt) # another global object that gets modified root = tk.Tk() btn = tk.Button(root, text="My Button") btn[''command''] = text_mod btn.pack(fill=''both'', expand=True) root.mainloop()

Mirror

Mi código es:

from Tkinter import * admin = Tk() def button(an): print an print ''het'' b = Button(admin, text=''as'', command=button(''hey'')) b.pack() mainloop()

El botón no funciona, imprime ''hey'' y ''het'' una vez sin mi comando, y luego, cuando presiono el botón, no pasa nada.


La opción de command toma una referencia a una función, que es una forma elegante de decir que necesita pasarle el nombre de la función. Cuando haces el button(''hey'') estás llamando al button función, y el resultado de eso se está dando a la opción de command .

Para pasar una referencia, debe usar solo el nombre, sin usar paréntesis o argumentos. Por ejemplo:

b = Button(... command = button)

Si desea pasar un parámetro como "oye", debe usar un pequeño código adicional:

  • Puede crear una función intermedia que se puede llamar sin su argumento y que luego llama a su función de button ,
  • Puede usar lambda para crear lo que se conoce como una función anónima . En todos los sentidos es una función, excepto que no tiene un nombre. Cuando llamas al comando lambda , devuelve una referencia a la función creada, lo que significa que puede usarse para el valor de la opción de command del botón.
  • Puedes usar functools.partial

Para mí, lambda es el más simple ya que no requiere ninguna importación adicional como functools.partial , aunque algunas personas piensan que functools.partial es más fácil de entender.

Para crear una función lambda que llame a su función de button con un argumento, haría algo como esto:

lambda: button(''hey'')

Terminas con una función que es funcionalmente equivalente a:

def some_name(): button(''hey'')

Como dije antes, lambda devuelve una referencia a esta función sin nombre. Como una referencia es lo que la opción de command espera, puede usar la dirección lambda en la creación del botón:

b = Button(... command = lambda: button(''hey''))

Hay una pregunta en este sitio que tiene muchos comentarios interesantes sobre lambda, en general. Vea la pregunta ¿Por qué las lambdas de Python son útiles? . Esa misma discusión tiene una respuesta que muestra cómo usar lambdas en un bucle cuando necesita pasar una variable a la devolución de llamada.

Finalmente, consulte la sección titulada Tkinter Callbacks en effbot.org para obtener un buen tutorial. La cobertura de lambda es bastante delgada, pero la información allí podría ser útil.


Necesita crear una función sin parámetros que pueda usar como comando:

b = Button(admin, text=''as'', command=lambda: button(''hey''))

Consulte la sección "Paso de argumento a devoluciones de llamada" de este documento .


No utilice ninguna palabra clave o argumento como entrada o paréntesis para su función. Esa es una solución muy fácil :)


button(''hey'') invoca la función, en lugar de configurarla como una devolución de llamada.