Partage
  • Partager sur Facebook
  • Partager sur Twitter

déplacement d'un dessin dans un canevas

    18 octobre 2018 à 0:16:57

    Bonjour.

    J'essaie de faire se déplacer un cercle, dans un canevas.

    Il doit se déplacer aux endroits où je clique, sur le canevas. Malheureusement, cela ne fonctionne pas.

    Pourriez-vous m'éclairer?

    Le script est le suivant:

    #Le programme doit modifier les coordonnées d'un cercle dans un canevas
    #pour lui faire prendre la position entrée par chaque clic
    
    from tkinter import *
    
    def clic(event):    
        global a, b #la fonction modifie les variables globales a et b
        a, b = event.x, event.y     #pour leur faire prendre les coordonnées du clic de souris
        lab.configure(text="coordonnées : X="+ str(a)+ "Y="+str(b))     #le label affiche les nouvelles coordonnées
        can.coords(rond, a, b)     #la méthode coords doit normalement modifier les coordonnées du dessin.
    
    ##Variables globales pour les coordonnées de l'objet "rond"
    a = 50
    b = 100
    
    ##Corps principal du programme##
    
    fen = Tk()      #fenêtre principale
    fen.title("exercice")
    can = Canvas(fen, bg="white",  height=200,  width=200)      #création du canevas de dessin
    can.grid(row=0)
    lab=Label(fen)      #création du label d'affichage des coordonées
    lab.grid(row=1)
    can.bind("<Button-1>", clic)
    rond = can.create_oval(a-10, b-10, a+10, b+10, fill="red")  #création de l'objet "rond"
    
    fen.mainloop()
    

    Merci à tous ceux qui sauront m'aider :-)

    -
    Edité par Cro-Magnon 18 octobre 2018 à 0:17:35

    • Partager sur Facebook
    • Partager sur Twitter
      18 octobre 2018 à 7:12:52

      Bonjour,

      Lors de la création de l'objet vous entrez les coordonnées de la boite, pour le déplacement dito.

      Le message envoyé ds la console est parlant ; tkinter.TclError: wrong # coordinates: expected 0 or 4, got 2.

      • Partager sur Facebook
      • Partager sur Twitter
        18 octobre 2018 à 11:30:19

        Merci beaucoup, je n'avais pas vu le message d'erreur. :-)

        J'essaie d'améliorer le programme, pour que l'objet ne soit déplaçable, dans le canevas, qu'après avoir été "sélectionné", par un clic de souris dessus.

        Pour l'instant mon idée est "d'enregistrer" le 1e clic dans une variable, à l'aide d'une fonction. Mais cela ne donne rien.

        Auriez-vous une idée sur la marche à suivre?

        Voici mon nouvel essai de script:

        from tkinter import *
        
        def clic1(event):   
            "la fonction enregistre le 1e clic sur l'objet"
            global clic_rouge
            x, y = event.x, event.y
            if x in rond and y in rond:     #si le clic a été effectué dans l'objet "rond"
                clic_rouge += 1                 #alors on enregistre le clic en incrémentant la variable
          
        def clic2(event):
        "la fonction utilise le second clic pour déplacer l'objet, seulement si l'objet a été "sélectionné" par la fonction clic1
        global a, b, clic_rouge #la fonction modifie les variables globales a et b et utilise la valeur de clic_rouge a, b = event.x, event.y #pour leur faire prendre les coordonnées du clic de souris if clic_rouge > 0: lab.configure(text="coordonnées : X="+ str(a)+ "Y="+str(b)) #le label affiche les nouvelles coordonnées can.coords(rond, a-10, b-10, a+10, b+10) #la méthode coords doit normalement modifier les coordonnées du dessin. ##Variables globales## clic_rouge = 0 #enregistrement du 1e clic de souris a = 50 #corrdonnées de l'objet "rond" b = 100 ##Corps principal du programme## fen = Tk() #fenêtre principale fen.title("exercice") can = Canvas(fen, bg="white", height=200, width=200) #création du canevas de dessin can.grid(row=0) lab=Label(fen) #création du label d'affichage des coordonées lab.grid(row=1) can.bind("<Button-1>", clic1) can.bind("<Button-1>", clic2) rond = can.create_oval(a-10, b-10, a+10, b+10, fill="red") #création des astres fen.mainloop()



        -
        Edité par Cro-Magnon 18 octobre 2018 à 11:32:59

        • Partager sur Facebook
        • Partager sur Twitter
          18 octobre 2018 à 13:14:42

          Quand vous créez l'objet avec create_oval, la variable rond va contenir un Id (voir avec print(rond)).

          Vous récupérez la boite de cet objet ( voir avec print(can.coords(rond))).

          1) vérifier que le premier clic (event.x et event.y) est bien ds la boite de l'objet ds sa position initiale. Si oui mettre une variable, par exemple DETECTION_CLIC_SUR_OBJET, à True.

          2) Créez une ligne (au bon endroit) Canvas.bind('<B1-Motion>',Move)

          3) Créez la def Move (event);

                  Je récupère event x et y

                  Si DETECTION_CLIC_SUR_OBJET est true alors:

                       Je bouge le rond avec canvas.coords (rond, coords de la boite)

          Normalement cela doit marcher.

          • Partager sur Facebook
          • Partager sur Twitter
            18 octobre 2018 à 16:19:50

            Je n'y arrive pas.

            J'ai fait la chose suivante:

            #Le programme doit modifier les coordonnées d'un cercle dans un canevas
            #pour lui faire prendre la position entrée par chaque clic
            
            from tkinter import *
            
            def clic1(event):   
                global coord,  deteclic
                x, y = event.x, event.y
            lab.configure(text="X = "+ str(x)+ "Y = "+ str(y))
              if x > coord[0] and x < coord[2] and y > coord[1] and y < coord[3]: #si les coordonnées du clic deteclic = True #sont inclus dans celles du rond, alors deteclic=True def move(event): global coord, deteclic if deteclic == True: #Lors du second clic, si deteclic ==True can.coords(rond, event.x, event.y) #alors on remplace les coordonnées du cercle avec les nouvelles ##Variables globales## deteclic = False #deteclic est fausse par défault a, b = 50, 50 #coordonnées de départ pour le cercle. ##Corps principal du programme## fen = Tk() #fenêtre principale fen.title("exercice") can = Canvas(fen, bg="white", height=200, width=200) #création du canevas de dessin can.grid(row=0) lab=Label(fen) #création du label d'affichage des coordonées lab.grid(row=1) can.bind("<Button-1>", clic1) #on lie les clics aux fonctions clic1 et move can.bind("<Button-1>", move) rond = can.create_oval(a-10, b-10, a+10, b+10, fill="red") #création du rond coord = can.coords(rond) #la variable qui contient la liste des coordonnées fen.mainloop()


            Je ne sais pas s'il s'agit d'un problème pour contrôler la valeur du premier clic (à ce niveau, j'ai créé la variable liste "coord", à laquelle j'ai comparée event.x et event.y, dans la fonction clic1), ou d'autre chose.

            Edit: J'ai peut être une piste. Quand je demande à la fonction clic1 d'afficher les coordonnées du premier clic, elle ne le fait uniquement que si j'enlève la ligne can.bind("<Button-1>", move).

            Ceci étant, je ne suis pas plus avancé car je ne vois toujours pas ce qui cloche.

            -
            Edité par Cro-Magnon 18 octobre 2018 à 16:33:41

            • Partager sur Facebook
            • Partager sur Twitter
              18 octobre 2018 à 20:20:36

              Quelques erreurs:

              - sur le deuxième can.bind il faut tester B1-motion (la souris bouge).

              - dans la def move, récupérer x, y = event.x, event.y (le pointeur de la souris s'est déplacé).

              - et ds le can.ccords injecter les 4 points de la boite dont le centre est x,y ci-dessus, comme lors de la création.

              Avec ces modifs cela fonctionne.

              Le test sur le clic n'est pas bon, je vous laisse chercher un peu...

              • Partager sur Facebook
              • Partager sur Twitter
                19 octobre 2018 à 13:04:12

                J'ai appliqué vos conseils. Tous fonctionne. Merci beaucoup! Ça fait plaisir d'avancer. Cela fait plusieurs jours que je buttais sur ce programme (quand ça veux pas... ça veux pas!)

                Une petite coquille encore, mais vu comme j'ai progressé, je ne désespère pas.

                1) J'ai utilisé le bind "<Double-1>", au lieu de motion, que je n'arrivais pas à utiliser. Mais je trouve ça dommage néanmoins de devoir faire appel à ce genre de stratagème pour ne pas bloquer le programme. N'y a-t-il pas une parade, pour pouvoir utiliser deux fois de suite "<Button-1>"?

                Le nouveau code:
                #Le programme doit modifier les coordonnées d'un cercle dans un canevas
                #pour lui faire prendre la position entrée par chaque clic
                
                from tkinter import *
                
                def clic1(event):   
                    global coord,  deteclic
                    x, y = event.x, event.y
                    lab.configure(text="X = "+ str(x)+ " Y = "+ str(y))
                    if x > coord[0] and x < coord[2] and y > coord[1] and y < coord[3]: #si les coordonnées du clic
                        deteclic = True     #sont inclus dans celles du rond, alors deteclic=True
                
                def move(event):
                    global deteclic
                    x, y = event.x, event.y
                    if deteclic == True:    #Lors du second clic, si deteclic ==True
                        can.coords(rond, x-10, y-10, x+10, y+10)  #alors on remplace les coordonnées du cercle avec les nouvelles
                    
                ##Variables globales##
                deteclic = False        #deteclic est fausse par défault
                a, b = 50, 50     #coordonnées de départ pour le cercle.
                
                ##Corps principal du programme##
                
                fen = Tk()      #fenêtre principale
                fen.title("exercice")
                can = Canvas(fen, bg="white",  height=200,  width=200)      #création du canevas de dessin
                can.grid(row=0)
                lab=Label(fen)      #création du label d'affichage des coordonées
                lab.grid(row=1)
                
                can.bind("<Button-1>", clic1)   #on lie les clics aux fonctions clic1 et clic2
                can.bind("<Double-1>", move)
                
                rond = can.create_oval(a-10, b-10, a+10, b+10, fill="red")  #création du rond
                coord = can.coords(rond)    #la variable qui contient la liste des coordonnées
                
                fen.mainloop()
                



                -
                Edité par Cro-Magnon 19 octobre 2018 à 13:09:39

                • Partager sur Facebook
                • Partager sur Twitter
                  19 octobre 2018 à 14:58:01

                  can.bind("<B1-Motion>", move) marche très bien chez moi.

                  Voir ce tuto ; http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

                  Votre ligne 10, telle qu'elle est écrite ne teste rien du tout, on clique 1 fois ds le blanc et cela déplace le cercle !

                  Si le but est de s'assurer que l'on a bien cliqué ds le cercle, il faut écrire: if (coord[0]<x<coord[2]) and (coord[1]<y<coord[3]):

                  • Partager sur Facebook
                  • Partager sur Twitter
                    19 octobre 2018 à 18:17:12

                    C'est bon, j'ai pu faire fonctionner "<B1-Motion>". J'avais fait une erreur de saisie du nom.

                    Le programme fonctionne bien, maintenant. Je continue mes recherches pour trouver comment gérer le problème du double <Button-1>, mais au moins j'ai pu avancer la dessus. J'ai compris pas mal de choses. Merci encore. :-)

                    • Partager sur Facebook
                    • Partager sur Twitter

                    déplacement d'un dessin dans un canevas

                    × 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