Bonjour,
J'essaie de générer une barre d'outils à la volée. Pour celà je boucle sur une liste contenant les libellés des boutons et je créé mes boutons.
# code simplifié pour l'exemple :
list = ["but1", "but2", "but3", "but4", "but5", "but6"]
for key in list:
ui.key = Button(ui, text=key, command=lambda:print(key))
ui.key.pack(side=LEFT, padx=2, pady=2)
Dans mon programme j'ai bien la barre d'outils suivante :
+——————————————————————————————————————————+
| [but1] [but2] [but3] [but4] [but5] [but6]|
+——————————————————————————————————————————+
Par contre lorsque je clique sur un bouton j'ai toujours la même action qui correspond à la dernière occurence de la liste (donc l'action de but6) :
click sur but1 affiche but6
click sur but2 affiche but6
click sur but3 affiche but6
click sur but4 affiche but6
click sur but5 affiche but6
click sur but6 affiche but6
Je suppose que c'est la fonction lambda: qui pose problème… Et j'aimerais savoir comment procéder pour définir mon callback correctement.
Merci.
# oubli paramètre lambda
Posté par niol (site web personnel) . Évalué à 2.
Peut-être que tu as oublié le paramètre à la fonction lambda. print(key) est simplifier par l'interpréteur au premier passage et le résultat simplifié est utilisé pour les suivants.
Essaye donc pour corriger :
[^] # Re: oubli paramètre lambda
Posté par niol (site web personnel) . Évalué à 2.
En fait je me suis planté.
[^] # Re: oubli paramètre lambda
Posté par JPEC . Évalué à 2.
Je m'étais basé sur cette documentation pour le callback et lambda :
http://effbot.org/zone/tkinter-callbacks.htm
# Namespace et closure.
Posté par GaMa (site web personnel) . Évalué à 6.
C'est un problème de python et pas de tkinter.
Lorsque tu parcours ta list et crées tes lambdas, tu crées n fonctions (6 dans ton cas) qui sont toutes liées au même namespace (dans lequel elles ont été créées).
Quand Tkinter appelle ces callbacks, elles vont toutes aller chercher la valeur de key dans le namespace les contenant. Comme elles partagent le même namespace, elle trouve la même valeur. Et la valeur de key, c'est "but6", la dernière valeur attribuer à key.
La solution est de forcer la "résolution" de key au moment où la lambda est créée et pas quand elle est exécutée.
Pour ce faire, l'idiome courant en python est d'utiliser un argument ayant une valeur par défaut:
Ainsi, lorsque la lambda est exécutée, elle utilise la valeur de k (son argument) qui à pour valeur la valeur de key (variable global) au moment de sa définition.
Il existe aussi une autre façon de faire, créer un namespace par fonction, dans lequel la closure ira chercher:
Matthieu Gautier|irc:starmad
[^] # Re: Namespace et closure.
Posté par JPEC . Évalué à 3.
Merci beaucoup !
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.