Tkinter, bouton et lambda.

Bonjour,

j'essaye de faire de jolis dessins en utlisant le module Tkinter. J'aimerais que ces dessins soient générés par l'appui sur un bouton de la fenêtre. J'ai donc crée une fonction dessin, que j'appelle depuis un bouton de ma fenêtre avec quelque-chose du genre:
bouton_dessin=Button(Fenetre,text='Dessiner',command=lambda: dessiner())
Cela fonctionne très bien, cependant si j'omets le "lambda", qui précède la commande dessiner(). Le dessin s'affiche sans que le bouton ne soit sollicité.
Quelqu'un pourrait-il m'expliquer pourquoi ce fameux lambda doit il nécessairement précéder la commande a exécuté ?

Bonne journée

F.

Réponses

  • L'argument "command" de ta fonction Button attend en paramètre une fonction : c'est l'action à exécuter quand on clique sur le bouton.

    Ainsi, tu peux mettre simplement :
    command=dessiner
    
    et non:
    command=dessiner()
    
    En effet dans le premier code, tu indiques juste quelle est la fonction à appeler ; dans le second extrait, tu appelles la fonction "dessiner" et tu indiques que sa valeur de retour est la command à effectuer quand on clique sur le bouton (ce qui n'a aucun sens...).

    Dans le deuxième extrait, tu appelles la fonction au moment de la construction du bouton, d'où le comportement que tu observes. Par contre, si tu cliques sur le bouton, tu dois avoir une erreur.

    La syntaxe lambda sert à construire des fonction "à la volée". Écrire:
    f = lambda: dessiner()
    bouton_dessin=Button(Fenetre,text='Dessiner',command=f)
    
    revient exactement au même que:
    def f():
        dessiner()
    bouton_dessin=Button(Fenetre,text='Dessiner',command=f)
    
    La (quasi)-seule différence tient dans le fait que lambda est une expression : tu peux la passer en argument sans
    avoir à écrire un "def ...".

    Ici, tu n'as pas d'intérêt à utiliser de lambda car ta fonction "dessiner" ne prend pas de paramètre. Ça serait utile si
    ta fonction "dessiner" prenait un paramètre (par exemple, répéter le dessin un certain nombre de fois). Imaginons que ce soit le cas, on pourrait alors faire :
    bouton_dessin1=Button(Fenetre,text='Dessiner 1 fois',command=lambda: dessiner(1))
    bouton_dessin2=Button(Fenetre,text='Dessiner 2 fois',command=lambda: dessiner(2))
    bouton_dessin3=Button(Fenetre,text='Dessiner 3 fois',command=lambda: dessiner(3))
    
    ce qui reviendrait exactement au même que:
    def dessiner1():
        dessiner(1)
    
    def dessiner2():
        dessiner(2)
    
    def dessiner3():
        dessiner(3)
    
    bouton_dessin1=Button(Fenetre,text='Dessiner 1 fois',command=dessiner1)
    bouton_dessin2=Button(Fenetre,text='Dessiner 2 fois',command=dessiner2)
    bouton_dessin3=Button(Fenetre,text='Dessiner 3 fois',command=dessiner3)
    
    (rappel: "command" doit être une fonction sans argument)
  • Super,

    merci de ces explications. Une seconde question, dans le code suivant, qui fonctionne:
    import matplotlib.pyplot as plt
    
    fig, ax = plt.subplots()
    
    ax.set_xlim(-100,100)
    ax.set_ylim(-100,100)
    
    col=['b', 'g', 'r', 'c', 'm', 'y', 'k', 'w']
    
    for a in range(30):
        c=plt.Circle((0,0),5*(30-a),fill=True,color=col[a%8])
        ax.add_artist(c)
    
    
    plt.show()
    

    Que contienne les variables fig et ax ? Pourquoi est il nécessaire d'user de ce subterfuge pour affiche un disque ?

    Bonne journée

    F.
Connectez-vous ou Inscrivez-vous pour répondre.