Supposons que j'ai fait ce qui suit Button
avec 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)
La méthode action
est appelée lorsque j'appuie sur le bouton, mais que faire si je souhaite transmettre des arguments à la méthode action
?
J'ai essayé avec le code suivant:
button = Tk.Button(master=frame, text='press', command=action(someNumber))
Cela appelle simplement la méthode immédiatement et le fait d'appuyer sur le bouton ne fait rien.
Réponses:
Je préfère personnellement utiliser
lambdas
dans un tel scénario, car imo est plus clair et plus simple et ne vous oblige pas non plus à écrire beaucoup de méthodes wrapper si vous n'avez pas le contrôle sur la méthode appelée, mais c'est certainement une question de goût.C'est ainsi que vous le feriez avec un lambda (notez qu'il y a aussi une implémentation de currying dans le module fonctionnel, vous pouvez donc l'utiliser aussi):
la source
partial
fonctionne dans ce cas."This just invokes the method immediately, and pressing the button does nothing"
se produit?callback=lambda x=x: f(x)
comme dansfs = [lambda x=x: x*2 for x in range(5)] ; print [f() for f in fs]
Cela peut également être fait en utilisant
partial
les functools de la bibliothèque standard , comme ceci:la source
button = Tk.Button(master=frame, text='press', command=partial(action, arg))
action_with_args = partial(action, arg1, arg2... argN)
Exemple d'interface graphique:
Disons que j'ai l'interface graphique:
Que se passe-t-il lorsqu'un bouton est enfoncé
Voyez que lorsque vous
btn
appuyez dessus, il appelle sa propre fonction, ce qui est très similaire à celuibutton_press_handle
de l'exemple suivant:avec:
Vous pouvez simplement penser que cette
command
option doit être définie comme la référence à la méthode que nous voulons appeler, similaire àcallback
dansbutton_press_handle
.Appel d'une méthode ( rappel ) lorsque le bouton est enfoncé
Sans arguments
Alors si je voulais
print
quelque chose lorsque le bouton est enfoncé, j'aurais besoin de définir:Faites très attention à l' absence de
()
avec laprint
méthode qui est omise dans le sens que: "C'est le nom de la méthode que je veux que vous appeliez lorsque vous appuyez dessus, mais ne l'appelez pas juste à l'instant même."Cependant, je n'ai pas passé d'arguments pour le,print
donc il a imprimé tout ce qu'il imprime lorsqu'il est appelé sans arguments.Avec argument (s)
Maintenant, si je voulais également passer des arguments à la méthode que je veux être appelée lorsque le bouton est enfoncé, je pourrais utiliser les fonctions anonymes, qui peuvent être créées avec une instruction lambda , dans ce cas pour la
print
méthode intégrée, comme suit :Appel de plusieurs méthodes lorsque vous appuyez sur le bouton
Sans pour autant arguments
Vous pouvez également y parvenir en utilisant une
lambda
déclaration, mais c'est considéré comme une mauvaise pratique et je ne l'inclurai donc pas ici. La bonne pratique consiste à définir une méthode distinctemultiple_methods
, qui appelle les méthodes souhaitées, puis à la définir comme rappel de la pression du bouton:Avec argument (s)
Afin de passer des arguments à la méthode qui appelle d'autres méthodes, utilisez à nouveau
lambda
instruction, mais d'abord:puis définissez:
Retour des objets à partir du rappel
Notez également que
callback
cela ne peut pas vraimentreturn
parce qu'il est uniquement appelé à l'intérieurbutton_press_handle
aveccallback()
par opposition àreturn callback()
. Cela fonctionne,return
mais pas n'importe où en dehors de cette fonction. Ainsi, vous devriez plutôt modifier les objets accessibles dans la portée actuelle.Exemple complet avec modification (s) d'objets globaux
L'exemple ci-dessous appellera une méthode qui change
btn
le texte de chaque fois que vous appuyez sur le bouton:Miroir
la source
La capacité de Python à fournir des valeurs par défaut pour les arguments de fonction nous donne une issue.
Voir: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html
Pour plus de boutons, vous pouvez créer une fonction qui renvoie une fonction:
la source
myX
etmyY
fonctionne parfaitement merci beaucoup.S'appuyant sur la réponse de Matt Thompsons: une classe peut être rendue appelable afin qu'elle puisse être utilisée à la place d'une fonction:
la source
La raison pour laquelle il appelle la méthode immédiatement et que le fait d'appuyer sur le bouton ne fait rien est qu'il
action(somenumber)
est évalué et que sa valeur de retour est attribuée en tant que commande pour le bouton. Donc, siaction
quelque chose imprime pour vous dire qu'il a été exécuté et qu'il retourneNone
, il vous suffit de l'exécuteraction
pour évaluer sa valeur de retour et de le donnerNone
comme commande pour le bouton.Pour avoir des boutons pour appeler des fonctions avec différents arguments, vous pouvez utiliser des variables globales, bien que je ne puisse pas le recommander:
Ce que je ferais, c'est créer un
class
objet dont les objets contiendraient toutes les variables requises et les méthodes pour les modifier au besoin:la source
Je pense que devrait résoudre ce problème
la source
La meilleure chose à faire est d'utiliser lambda comme suit:
la source
Je suis extrêmement en retard, mais voici une manière très simple de l'accomplir.
Enveloppez simplement la fonction que vous souhaitez utiliser dans une autre fonction et appelez la deuxième fonction en appuyant sur le bouton.
la source
var1
etvar2
dans le module principal, vous pouvez sauterfunction1
du tout et insérer uneprint
instructionfunction2
. Faites-vous référence à d'autres situations que je ne comprends pas?Les lambdas sont tous très bien, mais vous pouvez également essayer ceci (qui fonctionne dans une boucle for btw):
Cela fonctionne car lorsque la liaison est définie, une pression sur une touche transmet l'événement en tant qu'argument. Vous pouvez alors appeler des attributs hors de l'événement comme
event.char
pour obtenir "1" ou "UP" ect. Si vous avez besoin d'un argument ou de plusieurs arguments autres que les attributs d'événement. créez simplement un dictionnaire pour les stocker.la source
J'ai également rencontré ce problème auparavant. Vous pouvez simplement utiliser lambda:
la source
Utilisez un lambda pour transmettre les données d'entrée à la fonction de commande si vous avez plus d'actions à effectuer, comme celle-ci (j'ai essayé de le rendre générique, alors adaptez-vous):
Cela transmettra les informations de l'événement à la fonction de bouton. Il y a peut-être des façons plus pythonesques d'écrire cela, mais cela fonctionne pour moi.
la source
JasonPy - quelques petites choses ...
si vous collez un bouton dans une boucle, il sera créé encore et encore et encore ... ce qui n'est probablement pas ce que vous voulez. (peut etre c'est)...
La raison pour laquelle il obtient toujours le dernier index est que les événements lambda sont exécutés lorsque vous cliquez dessus, et non au démarrage du programme. Je ne suis pas sûr à 100% de ce que vous faites, mais essayez peut-être de stocker la valeur lorsqu'elle est créée, puis appelez-la plus tard avec le bouton lambda.
par exemple: (n'utilisez pas ce code, juste un exemple)
alors vous pouvez dire ...
J'espère que cela t'aides!
la source
Un moyen simple serait de configurer
button
aveclambda
la syntaxe suivante:la source
Pour la postérité: vous pouvez également utiliser des classes pour réaliser quelque chose de similaire. Par exemple:
Le bouton peut alors être simplement créé par:
Cette approche vous permet également de changer les arguments de la fonction en définissant ie
instance1.x = 3
.la source
Vous devez utiliser
lambda:
la source
Utiliser lambda
production:
la source