Partage
  • Partager sur Facebook
  • Partager sur Twitter

Déplacer des objets à la souris

    2 février 2023 à 7:46:36

    Bonjour,


    Je reprends un fil précédent avec une focale plus spécifique et un bout de code dédié à ma problématique.

    J'ai deux objets rect1 et rect2.

    Si je clique dessus, je dois pouvoir les déplacer à la souris. diifx et diffy me permettent de corriger la position de l'objet pendant le déplacement sinon il est redessiné à partir de son point en haut à gauche, or il faut tenir compte de la position relative du pointeur de la souris dans la bbox.

    Si je clique ailleurs, je veux que ça trace un rectangle bleu (comme pour sélectionner des objets). Donc quand on relâche la souris, le rectangle doit disparaître.

    Voilà le code, pensez-vous qu'il peut être amélioré ? Car si ça fonctionne impeccable sous Linux, j'ai un scintillement important du rectangle bleu sous Windows.

    Merci

    from tkinter import *
    
    #Fenêtre
    fenetre = Tk()
    larg=fenetre.winfo_screenwidth()
    haut=fenetre.winfo_screenheight()
    fenetre.title("Entraînement")
    fenetre.attributes("-fullscreen", 1)
    zone_princ=Canvas(fenetre, width=larg, height=haut)
    zone_princ.grid(row=1,column=1)
    # Je crée deux rectangles qui sont amenés à bouger
    rect1 = zone_princ.create_rectangle(50, 50, 100, 100, outline="black", fill="red", width=5)
    rect2 = zone_princ.create_rectangle(150, 150, 200, 200, outline="black", fill="green", width=5)
    
    DETECTION_CLIC_SUR_OBJET=0
    
    def Clic(event):
        global DETECTION_CLIC_SUR_OBJET, diffx, diffy, objetbouge, select, rectx, recty
        X = event.x
        Y = event.y
        # Je vérifie si on a cliqué sur un objet
        for i in (zone_princ.find_all()):
            [x1,y1,x2,y2] = zone_princ.bbox(i)
            if x1 < X < x2 and y1 < Y < y2:
                DETECTION_CLIC_SUR_OBJET = 1
                objetbouge=i
                zone_princ.tag_raise(objetbouge)
                diffx=X-x1
                diffy=Y-y1
        #Si on n'a pas cliqué sur un objet je commence à dessiner un rectangle bleu
        if DETECTION_CLIC_SUR_OBJET==0:
            select=zone_princ.create_rectangle(X,Y,X,Y,outline="blue", width=3)
            rectx=X
            recty=Y
            DETECTION_CLIC_SUR_OBJET = 2
    
    def Drag(event):
        global select
        #Si on a cliqué sur un objet, on le déplace
        if DETECTION_CLIC_SUR_OBJET==1:
            X = event.x
            Y = event.y
            # mise à jour de la position de l'objet
            zone_princ.moveto(objetbouge, X-diffx,Y-diffy)
            ok=1
        #Si on n'a pas cliqué sur un objet, on aggrandit le rectangle en fonction de la position du pointeur de souris
        elif DETECTION_CLIC_SUR_OBJET == 2:
            X = event.x
            Y = event.y
            zone_princ.delete(select)
            select=zone_princ.create_rectangle(rectx,recty,X,Y,outline="blue", width=3)
    
    
    def End(event):
        #Au relâchement du bouton de la souris, on efface le rectangle
        global DETECTION_CLIC_SUR_OBJET, select
        if DETECTION_CLIC_SUR_OBJET == 2:
            zone_princ.delete(select)
            DETECTION_CLIC_SUR_OBJET =0
    
    #événements souris
    zone_princ.bind('<Button-1>',Clic) # évévement clic gauche (press)
    zone_princ.bind('<B1-Motion>',Drag) # événement bouton gauche enfoncé (hold down)
    zone_princ.bind('<ButtonRelease-1>',End) # événement bouton gauche relâché (hold down)
    
    fenetre.bind_all('<Escape>',lambda event: fenetre.destroy())
    
    fenetre.mainloop()






    • Partager sur Facebook
    • Partager sur Twitter
      2 février 2023 à 8:55:59

      Salut,

      Si l'on sélectionne un des 2 carrés, on a plus la possibilité de tracer le fameux rectangle bleu... Tu dois dans ta fonction End() sortir DETECTION_CLIC_SUR_OBJET =0 de ta condition if :

      def End(event):
          #Au relâchement du bouton de la souris, on efface le rectangle
          global DETECTION_CLIC_SUR_OBJET, select
          if DETECTION_CLIC_SUR_OBJET == 2:
              zone_princ.delete(select)
          DETECTION_CLIC_SUR_OBJET =0

      Après, trop de globals et revoir les conventions de nommage ;)


      • Partager sur Facebook
      • Partager sur Twitter
        2 février 2023 à 12:04:46

        Oui, tout à fait.

        C'est bien le cas dans mon programme complet. J'ai juste fait cette erreur en transférant le bout de code pour l'exemple.

        Dans le programme complet le DETECTION_CLIC_SUR_OBJET =0
        est présent plus loin.

        Pour les variables globales, desquelles puis-je me "passer" ?

        Je n'ai pas trouvé d'autre moyen par exemple pour DETECTION_CLIC_SUR_OBJET car les deux fonctions s'en servent.

        • Partager sur Facebook
        • Partager sur Twitter
          2 février 2023 à 13:36:41

          ArnaudJouski a écrit:

          Pour les variables globales, desquelles puis-je me "passer" ?

          En utilisant les fonctionnalités d'un Canvas tkinter, vous devriez pouvoir vous passer de toutes.

          Après, select, move, drop,... c'est d'abord un algorithme à décrire pas un code qui va faire on ne sait trop quoi sans utiliser les fonctionnalités du Canvas qui pourraient aider.

          Par exemple la détection d'un clic sur un objet peut se faire en cherchant ce qui est pas loin du tag current ou en faisant un bind qui se déclenche lorsqu'on clique sur un des items du Canvas (comme ça il y en a toujours un...).

          Et ce n'est qu'après avoir compris ce que pouvait faire le Canvas que vous allez pouvoir programmer "avec"... plutôt que de refaire de votre côté ce que le Canvas fait déjà.

          • Partager sur Facebook
          • Partager sur Twitter

          Déplacer des objets à la souris

          × 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