Partage
  • Partager sur Facebook
  • Partager sur Twitter

[tkinter] Les commandes se lancent toutes seules

    10 novembre 2017 à 2:30:19

    Salut,

    Je débute en Python et mon livre commence a aborder les fenêtres avec le module tkinter.

    Je dois réaliser un drapeau olympique en faisant dessiner chaque anneau au moment du click sir le bouton approprié. cependant quand j’exécute mon programme tous les anneaux apparaissent déjà dessinés. J'ai ensuite rajouter un bouton pour effacer tout et pouvoir tester mes boutons, mais le canvas reste vide et les boutons ne marchent pas.

    Je comprends pas pourquoi mes boutons sont interprétés sans qu'on clique dessus. Merci pour votre aide

    """
    8.7 a) Créez un court programme qui dessinera les 5 anneaux olympiques dans un rectangle de
    fond blanc (white). Un bouton <Quitter> doit permettre de fermer la fenêtre.
    b) Modifiez le programme ci-dessus en y ajoutant 5 boutons. Chacun de ces boutons
    provoquera le tracé de chacun des 5 anneaux
    """
    
    from tkinter import *
    
    # Definition des fonctions locales
    def anneau(cx,cy,couleur):
        'Crée un anneau olympique'
        x1,x2,y1,y2=cx-50,cx+50,cy-50,cy+50
        can1.create_oval(x1,y1,x2,y2,width=5,outline=couleur)
    
    # --- Programme Principal ---
    
    # Création du widget principal ("maître") :
    fen1 = Tk()
    
    # création des widgets "esclaves" :
    can1 = Canvas(fen1,bg='white',height=300,width=600)
    can1.pack(side=LEFT)
    bou1 = Button(fen1,text='Quitter',command=fen1.quit)
    bou1.pack(side=BOTTOM)
    bou2=Button(fen1,text="Anneau Bleu",command=anneau(180,120,'Light Blue'))
    bou2.pack()
    bou3=Button(fen1,text="Anneau Noir",command=anneau(300,120,'Black'))
    bou3.pack()
    bou4=Button(fen1,text="Anneau Rouge",command=anneau(420,120,'Red'))
    bou4.pack()
    bou5=Button(fen1,text="Anneau Jaune",command=anneau(240,180,'Yellow'))
    bou5.pack()
    bou6=Button(fen1,text="Anneau Vert",command=anneau(360,180,'Green'))
    bou6.pack()
    # bou7=Button(fen1,text="Effacer",command=can1.delete("all"))
    # bou7.pack()
    
    fen1.mainloop() # démarrage du réceptionnaire d’événements
    
    fen1.destroy() # destruction (fermeture) de la fenêtre



    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      10 novembre 2017 à 8:35:52

      Le paramètre command prend en argument une fonction, pas le résultat d'une fonction. Je te laisse méditer un peu à ça, je pense que ça suffit pour que tu comprennes le problème dans ton code.
      • Partager sur Facebook
      • Partager sur Twitter
        10 novembre 2017 à 15:59:16

        Salut,

        Pour en ajouter, c'est un peu plus complexe qu'enlever les parenthèses, puisque vous avez des arguments pour la fonction.

        À moins de créer une fonction unique, pour chaque bouton (à la place de anneau()), vous devrez utiliser la fonction anonyme lambda. Elle permettra de faire passer des arguments.

        Il y a beaucoup d'exemple, faites une recherche :)

        Bonne chance

        A+

        • Partager sur Facebook
        • Partager sur Twitter
          14 novembre 2017 à 14:30:47

          Salut,

          Merci pour vos réponses. J'ai utilisé la méthode de crée une commande par bouton, c'est celle que je comprends le mieux a mon niveau. Maintenant ça  marche :)

          """
          8.7 a) Créez un court programme qui dessinera les 5 anneaux olympiques dans un rectangle de
          fond blanc (white). Un bouton <Quitter> doit permettre de fermer la fenêtre.
          b) Modifiez le programme ci-dessus en y ajoutant 5 boutons. Chacun de ces boutons
          provoquera le tracé de chacun des 5 anneaux
          """
          
          from tkinter import *
          
          # Definition des fonctions locales
          ## fonction principales
          def anneau(i):
              'Crée un anneau olympique'
              xy=[[180,120],[300,120],[420,120],[240,180],[360,180]]
              col=['Light Blue','Black','Red','Yellow','Green']
              x,y,r=xy[i][0],xy[i][1],50
              can1.create_oval(x-r,y-r,x+r,y+r,width=5,outline=col[i])
          
          ## fonction des boutons
          def anneau0():
              anneau(0)
          def anneau1():
              anneau(1)
          def anneau2():
              anneau(2)
          def anneau3():
              anneau(3)
          def anneau4():
              anneau(4)
          
          # --- Programme Principal ---
          
          # Création du widget principal ("maître") :
          fen1 = Tk()
          
          # création des widgets "esclaves" :
          can1 = Canvas(fen1,bg='white',height=300,width=600)
          can1.pack(side=LEFT)
          bou1 = Button(fen1,text='Quitter',command=fen1.quit)
          bou1.pack(side=BOTTOM)
          bou2=Button(fen1,text="Anneau Bleu",command=anneau0)
          bou2.pack()
          bou3=Button(fen1,text="Anneau Noir",command=anneau1)
          bou3.pack()
          bou4=Button(fen1,text="Anneau Rouge",command=anneau2)
          bou4.pack()
          bou5=Button(fen1,text="Anneau Jaune",command=anneau3)
          bou5.pack()
          bou6=Button(fen1,text="Anneau Vert",command=anneau4)
          bou6.pack()
          
          fen1.mainloop() # démarrage du réceptionnaire d’événements
          
          fen1.destroy() # destruction (fermeture) de la fenêtre



          • Partager sur Facebook
          • Partager sur Twitter
            14 novembre 2017 à 19:08:07

            Salut,

            Avant de commencer, Bravo :) Vous avez trouvé une des solutions possibles :)

            Si vous voulez savoir comment lambda fonctionne, il y quelques exemples sur le forum d'OC.

            Je me rappelle, qu'au début cela paraissait compliqué.

            C'est une fonction normal, qui se tient en une ligne seulement. Elle prends le nombre d'arguments que vous voulez (y compris les arguments optionnels), mais ne retourne la valeur, que d'une seule expression. (Pas le choix..)

            Voici deux exemples simples, au cas.:

            ###################
            #### Exemple 1 ####
            ###################
            
            ## Fonction normal:
            def carrer_normal(x):
                return x ** 2
            
            ## Fonction LAMBDA:
            carrer_lambda = lambda x: x**2
            
            ## MAIN:
            print(carrer_normal(2)) # --> 4
            print(carrer_lambda(2)) # --> 4
            
            
            ###################
            #### Exemple 2 ####
            ###################
            
            class Salut(object):
                def __init__(self):
                    self.allo = 3
                    self.bonjour = 5
            
            ## Fonction Normal:
            def somme_normal(x):
                return x.allo + x.bonjour
            
            ## Fonction LAMBDA:
            somme_lambda = lambda x: x.allo + x.bonjour
            
            ## MAIN:
            salut = Salut()
            print(somme_normal(salut)) # --> 8
            print(somme_lambda(salut)) # --> 8

            Voici un exemple, avec votre code et la fonction zip():

            import tkinter as tk
            
            
            LST_XY = [
                [180,120],[300,120],[420,120], [240,180],[360,180]
            ]
            LST_COLORS =[
                'Light Blue','Black','Red','Yellow','Green'
            ]
            LST_TEXTES = [
                'Bleu', 'Noir', 'Rouge', 'Jaune', 'Vert'
            ]
            
            
            fenetre = tk.Tk()
            
            canva = tk.Canvas(fenetre)
            canva.pack()
            
            def anneau(position, couleur):
                x,y,r = position[0], position[1], 50
                canva.create_oval(x-r,y-r,x+r,y+r,
                                 width=5,outline=couleur)
            
            for (xy, color, texte) in zip(LST_XY, LST_COLORS, LST_TEXTES):
                
                bouton = tk.Button(
                    fenetre, text=texte,
                    command=lambda pos=xy, col=color: anneau(pos, col))
            
                bouton.pack()
            
            
            fenetre.mainloop()
            

            À vous de choisir ce que vous préférez. Sauf qu'en même temps, vous faites ces exercies pour apprendre. Lambda vous sera peut-être utile, sans que vous le sachez.
            De plus, votre code possède beaucoup de répétitions. Vous pourriez les éliminer... Plus vous allez avancer dans votre code, plus les répétitions seront fréquentes. Aussi bien les supprimer dès le départ (Surtout, pour des widgets) :)

            Bref, comme je vous dis, à vous de choisir.

            Dans tous les cas, Bravo! Lâchez pas la patate.

            Bonne chance

            A+

            -
            Edité par nolimitech 14 novembre 2017 à 19:18:05

            • Partager sur Facebook
            • Partager sur Twitter
              15 novembre 2017 à 2:16:57

              Merci pour vos encouragements.

              j'aime beaucoup votre résolution de mon exercice, j'arrive presque a tout comprendre est c'est beaucoup plus alléger. j'ai cependant quelques questions qui me viennent a l'esprit :

              1/ première ligne, vous importez tkinter avec une commande différente que je n'est pas encore vue. Si je comprends bien cette méthode elle m'oblige ensuite a rajouter tk. devant chaque fonction de tkinter. Je suppose que son intérêt est de pouvoir avoir plusieurs fonction canvas dans plusieurs modules différents par exemple. Du coup me conseiller vous de toujours importer mes modules de cette manière?

              2/ les trois variables utilisées par la fonction zip() sont en majuscule. Dans mon livre on m'apprends que la convention pour les variables est de les écrire en minuscule avec des underscore pour séparer les mots, est ce une convention spéciale pour la fonction zip() ou une obligation?

              3/ Pour moi, lambda ressemble a un joker qui m'évite d'écrire la fonction pour la commande des boutons et de prendre directement ma fonction pour la création de l'anneau comme je voulais le faire au départ, je suis bien content d'en comprendre le fonctionnement.

              J'apprends Python pour mon plaisir personnel, parce que mon grand père disait qu'on est jamais trop vieux pour apprendre ? Mais je suis encore un vrai débutant même si j'avance dans le livre. Vous voyez, j'avais cherché a comprendre lambda a la suite de votre message mais il m'est encore difficile de comprendre le code des autres alors que votre correction de mon exercice est limpide pour moi. Surement car je l'ai déjà résolu a ma manière et que du coup j'ai déjà une idée de ce que raconte le code ...

              Merci beaucoup

              ah et j'aurais une dernière question pratique, comment on passe le sujet en résolu?

              • Partager sur Facebook
              • Partager sur Twitter

              [tkinter] Les commandes se lancent toutes seules

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown