Cómo configurar el texto / valor / contenido de un widget `Entry` usando un botón en tkinter

Estoy tratando de configurar el texto de un widget de Entry usando un botón en una GUI usando el módulo tkinter .

Esta GUI es para ayudarme a clasificar miles de palabras en cinco categorías. Cada una de las categorías tiene un botón. Esperaba que usar un botón me acelerara significativamente y quiero revisar las palabras cada vez que de otra manera solo usaría el botón y hacer que la GUI procesara la palabra actual y trajera la siguiente.

Los botones de comando por alguna razón no se comportan como yo quiero que lo hagan. Esto es un ejemplo:

 win = Tk() v = StringVar() def setText(word): v.set(word) a = Button(win, text="plant", command=setText("plant") a.pack() b = Button(win, text="animal", command=setText("animal")) b.pack() c = Entry(win, textvariable=v) c.pack() win.mainloop() 

Hasta ahora, cuando soy capaz de comstackr, el clic no hace nada.

Es posible que desee utilizar el método de insert .

Este script inserta un texto en la Entry . El texto insertado se puede cambiar en el parámetro de command del botón.

 from tkinter import * def set_text(text): e.delete(0,END) e.insert(0,text) return win = Tk() e = Entry(win,width=10) e.pack() b1 = Button(win,text="animal",command=lambda:set_text("animal")) b1.pack() b2 = Button(win,text="plant",command=lambda:set_text("plant")) b2.pack() win.mainloop() 

Si usa una “variable de texto” tk.StringVar() , simplemente puede set() eso.

No es necesario utilizar la entrada eliminar e insertar. ¡Además, esas funciones no funcionan cuando la Entrada está deshabilitada o es de solo lectura! Sin embargo, el método de variable de texto también funciona bajo esas condiciones.

 import Tkinter as tk ... entryText = tk.StringVar() entry = tk.Entry( master, textvariable=entryText ) entryText.set( "Hello World" ) 

Una forma sería heredar una nueva clase, EntryWithSet y set método de definición de set que haga uso de los métodos de delete e insert de los objetos de la clase de Entry :

 try: # In order to be able to import tkinter for import tkinter as tk # either in python 2 or in python 3 except ImportError: import Tkinter as tk class EntryWithSet(tk.Entry): """ A subclass to Entry that has a set method for setting its text to a given string, much like a Variable class. """ def __init__(self, master, *args, **kwargs): tk.Entry.__init__(self, master, *args, **kwargs) def set(self, text_string): """ Sets the object's text to text_string. """ self.delete('0', 'end') self.insert('0', text_string) def on_button_click(): import random, string rand_str = ''.join(random.choice(string.ascii_letters) for _ in range(19)) entry.set(rand_str) if __name__ == '__main__': root = tk.Tk() entry = EntryWithSet(root) entry.pack() tk.Button(root, text="Set", command=on_button_click).pack() tk.mainloop() 

Tu problema es que cuando haces esto:

 a = Button(win, text="plant", command=setText("plant")) 

intenta evaluar qué configurar para el comando. Así que cuando se crea una instancia del objeto Button , en realidad llama a setText("plant") . Esto es incorrecto porque todavía no desea llamar al método setText. Luego toma el valor de retorno de esta llamada (que es None ) y lo establece en el comando del botón. Es por eso que hacer clic en el botón no hace nada, porque no hay un comando configurado para ello.

Si haces lo que Milan Skála sugiere y usa una expresión lambda, entonces tu código funcionará (asumiendo que arreglas la sangría y los paréntesis).

En lugar de command=setText("plant") , que en realidad llama a la función, puede configurar command=lambda:setText("plant") que especifica algo que llamará a la función más adelante, cuando quiera llamarla.

Si no te gustan las lambdas, otra forma (un poco más incómoda) sería definir un par de funciones para hacer lo que quieras:

 def set_to_plant(): set_text("plant") def set_to_animal(): set_text("animal") 

y luego puede usar command=set_to_plant y command=set_to_animal – estos evaluarán las funciones correspondientes, pero definitivamente no son lo mismo que command=set_to_plant() que, por supuesto, evaluarían a None nuevamente.

Puede elegir entre los dos métodos siguientes para configurar el texto de un widget de Entry . Para los ejemplos, suponga que la biblioteca importada import tkinter as tk y root root = tk.Tk() .


  • Método A: usar delete e insert

    Widget Entry proporciona métodos de delete e insert que se pueden usar para establecer su texto en un nuevo valor. Primero, tendrá que eliminar cualquier texto antiguo anterior de Entry con delete que necesite las posiciones donde comenzar y finalizar la eliminación. Ya que queremos eliminar el texto antiguo completo, comenzamos en 0 y terminamos en donde sea que esté el final actualmente. Podemos acceder a ese valor a través de END . Luego, la Entry está vacía y podemos insertar new_text en la posición 0 .

     entry = tk.Entry(root) new_text = "Example text" entry.delete(0, tk.END) entry.insert(0, new_text) 

  • Método B: Utilice StringVar

    entry_text crear un nuevo objeto StringVar llamado entry_text en el ejemplo. Además, su widget de Entry debe crearse con el argumento textvariable palabra clave textvariable . Luego, cada vez que cambie entry_text con set , el texto se mostrará automáticamente en el widget de Entry .

     entry_text = tk.StringVar() entry = tk.Entry(root, textvariable=entry_text) new_text = "Example text" entry_text.set(new_text) 

  • Ejemplo de trabajo completo que contiene ambos métodos para configurar el texto a través de un Button :

    Esta ventana

    captura de pantalla

    es generado por el siguiente ejemplo de trabajo completo:

     import tkinter as tk def button_1_click(): # define new text (you can modify this to your needs!) new_text = "Button 1 clicked!" # delete content from position 0 to end entry.delete(0, tk.END) # insert new_text at position 0 entry.insert(0, new_text) def button_2_click(): # define new text (you can modify this to your needs!) new_text = "Button 2 clicked!" # set connected text variable to new_text entry_text.set(new_text) root = tk.Tk() entry_text = tk.StringVar() entry = tk.Entry(root, textvariable=entry_text) button_1 = tk.Button(root, text="Button 1", command=button_1_click) button_2 = tk.Button(root, text="Button 2", command=button_2_click) entry.pack(side=tk.TOP) button_1.pack(side=tk.LEFT) button_2.pack(side=tk.LEFT) root.mainloop()