J'essaie de définir le texte d'un widget Entry
à l'aide d'un bouton d'une interface graphique utilisant le module tkinter
.
Cette interface graphique m'aide à classer des milliers de mots en cinq catégories. Chacune des catégories a un bouton. J'espérais que l'utilisation d'un bouton m'accélérerait de manière significative et je voudrais vérifier les mots à chaque fois sinon je voudrais simplement utiliser le bouton et laisser l'interface graphique traiter le mot actuel et apporter le mot suivant.
Les boutons de commande pour une raison quelconque ne se comportent pas comme je le souhaite. Ceci est un exemple:
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()
Jusqu'ici, quand je suis capable de compiler, le clic ne fait rien.
Vous voudrez peut-être utiliser la méthode insert
.
Ce script insère un texte dans Entry
. Le texte inséré peut être modifié dans le paramètre command
du bouton.
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 vous utilisez une "variable de texte" tk.StringVar()
, vous pouvez simplement set()
that.
Pas besoin d'utiliser l'entrée supprimer et insérer. De plus, ces fonctions ne fonctionnent pas lorsque l'entrée est désactivée ou en lecture seule! Cependant, la méthode de variable de texte fonctionne également dans ces conditions.
import Tkinter as tk
...
entryText = tk.StringVar()
entry = tk.Entry( master, textvariable=entryText )
entryText.set( "Hello World" )
Une solution serait d'hériter d'une nouvelle classe, EntryWithSet
, et de définir la méthode set
qui utilise les méthodes delete
et insert
des objets Entry
class:
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 __== '__main__':
root = tk.Tk()
entry = EntryWithSet(root)
entry.pack()
tk.Button(root, text="Set", command=on_button_click).pack()
tk.mainloop()
Votre problème est que quand vous faites ceci:
a = Button(win, text="plant", command=setText("plant"))
il essaie d'évaluer ce qu'il faut définir pour la commande. Ainsi, lors de l'instanciation de l'objet Button
, il appelle en réalité setText("plant")
. C'est faux, car vous ne voulez pas encore appeler la méthode setText. Ensuite, il prend la valeur de retour de cet appel (qui est None
) et la définit comme commande du bouton. C'est pourquoi cliquer sur le bouton ne fait rien car il n'y a pas de commande pour cela.
Si vous suivez les instructions de Milan Skála et utilisez plutôt une expression lambda, votre code fonctionnera (si vous corrigez l'indentation et les parenthèses).
Au lieu de command=setText("plant")
, qui en fait appelle la fonction, vous pouvez définir command=lambda:setText("plant")
qui spécifie quelque chose qui appellera la fonction ultérieurement, lorsque vous souhaitez l'appeler.
Si vous n'aimez pas les lambdas, une autre façon (légèrement plus lourde) serait de définir une paire de fonctions pour faire ce que vous voulez:
def set_to_plant():
set_text("plant")
def set_to_animal():
set_text("animal")
et alors vous pouvez utiliser command=set_to_plant
et command=set_to_animal
- ceux-ci seront évalués en fonction des fonctions correspondantes, mais sont certainement pas identiques à command=set_to_plant()
, ce qui bien sûr serait évalué à None
à nouveau.
Vous pouvez choisir entre les deux méthodes suivantes pour définir le texte d'un widget Entry
. Pour les exemples, supposons que la bibliothèque importée import tkinter as tk
et la fenêtre racine root = tk.Tk()
.
Méthode A: Utiliser delete
et insert
Le widget Entry
fournit les méthodes delete
et insert
qui peuvent être utilisées pour définir le texte avec une nouvelle valeur. Tout d'abord, vous devez supprimer tout ancien texte de Entry
avec delete
qui nécessite les positions pour commencer et terminer la suppression. Puisque nous voulons supprimer l’ancien texte complet, nous commençons par 0
et se terminons à l’endroit où se trouve actuellement la fin. Nous pouvons accéder à cette valeur via END
. Ensuite, la Entry
est vide et nous pouvons insérer new_text
à la position 0
.
entry = tk.Entry(root)
new_text = "Example text"
entry.delete(0, tk.END)
entry.insert(0, new_text)
Méthode B: Utiliser StringVar
Vous devez créer un nouvel objet StringVar
appelé entry_text
dans l'exemple. De plus, votre widget Entry
doit être créé avec l'argument de mot clé textvariable
. Ensuite, chaque fois que vous modifiez entry_text
avec set
, le texte s'affichera automatiquement dans le widget Entry
.
entry_text = tk.StringVar()
entry = tk.Entry(root, textvariable=entry_text)
new_text = "Example text"
entry_text.set(new_text)
Exemple de travail complet contenant les deux méthodes pour définir le texte via Button
:
Cette fenêtre
est généré par l'exemple de travail complet suivant:
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()