Partage
  • Partager sur Facebook
  • Partager sur Twitter

Structuration image sous tkinter

tkinter

Sujet résolu
    20 juillet 2016 à 16:03:46

    Bonjour,

    Ayant appris Python via le site du Zéro (openclassroom pour les intimes), je me suis mis à coder pour un projet de gestion forestière.

    Il s'agit de tracer sur une carte des carrés délimitants chacun une zone (parcelle); ensuite on récupère les coordonnées du carré dans un fichier, et on nomme ainsi la parcelle comme celà (après, on la relie à des caractéristiques).

    Vous me direz qu'il est peut-être plus pratique de prendre un logiciel de cartographie. Deux raisons pour ne pas le prendre, celui que j'ai trouvé marche sur python2 et secundo je désire m'entraîner, d'autant plus que je me dis que celà pourra servir à d'autres.

    Voici mon code qui est un peu fouillis, composé à l'aide d'infos dénichées sous de multiples tutos où je trouve tout et son contraire.

    Pourriez-vous m'aider à l'organiser et à remédier aux problèmes? Cà va faire un mois que je butte...

    import tkinter as tk
    from PIL import Image, ImageTk


    #On définit la racine de la fenêtre
    root = tk.Tk()

    #On définit la classe principale du programme
    class Parcelle(tk.Frame):
        """Cette classe est un test reprenant tout le programme
        hormis ce qui concerne la fenêtre"""

    #On définit la fonction event pour pouvoir
    #la rappeler plus tard
        def Clic(self, event):

            """ Gestion de l'événement Clic gauche sur la zone graphique"""
        # on dessine un carré dès que l'on clique gauche
            self.x = event.x
            self.y = event.y
            CompteurCarre += 1

    #On créée les composantes du carré...
            r = 20
            xpr = self.x+r
            xmr = self.x-r
            ypr = self.y+r
            ymr = self.y-r
       
            print("La zone carréée a pour coordonnées: "+str(xpr)+", "+str(xmr)+", "+str(ypr)+", "+str(ymr)+"; ce carré est le numéro "+str(CompteurCarre))
    #que l'on écrit ensuite dans un fichier.
    #On dessinera le carré dans la fonction CreerImage plus loin
            with open("Coord.txt", "a") as Coordonnees:
                for ligne in Coordonnees:
                    if 540 < self.xpr < 570 and 500 < self.xmr < 540 and 180 < self.ypr < 220 and 155 < self.ymr < 170:
                        Coordonnees.write("La zone carréée a pour coordonnées: {0}, {1}, {2}, {3}, {4};\
                                         ce carré est le numéro {5}.Vous êtes dans la parcelle de\
                                         Lorilloux.".format(str(xpr),str(xmr),str(ypr),str(ymr),\
                                         str(CompteurCarre)))
                    else:
                        Coordonnees.write("La zone carréée a pour coordonnées: {0}, {1}, {2}, {3}, {4};\
                                         ce carré est le numéro {5}.".format(str(xpr),str(xmr),str(ypr),str(ymr),\
                                         str(CompteurCarre)))

    #On définit le constructeur de la classe principale parcelle
        def __init__(self, master = None):
            """Constructeur mettant en relief l'évènement Souris"""
            tk.Frame.__init__(self, master)
            self.pack()
            self.CreerImage()

    #On créée l'image
        def CreerImage(self):

            self.canvas = tk.Canvas(self, width=1000, height=800)
            self.canvas.pack(side='left')
            self.image = Image.open('parcelles_IX_XVI.jpg')
            self.photo = ImageTk.PhotoImage(self.image)


            self.canvas.create_image(0,0, anchor=tk.NW, image=self.photo)
    # La méthode bind() permet de lier un événement avec une fonction :
    # un clic gauche sur la zone graphique provoquera l'appel de la fonction utilisateur Clic()


            self.canvas.bind('<<button1>>', self.Clic)
            self.canvas.create_rectangle(self.x+r, self.x-r, self.y+r, self.y-r, outline='black',fill='green')

      # Création d'un widget Button (bouton Quitter)
            self.quitter = tk.Button(self, text ='Quitter', command = root.destroy)
            self.quitter.pack(side='bottom')




    # La méthode bind() permet de lier un événement avec une fonction :
    # un clic gauche sur la zone graphique provoquera l'appel de la fonction utilisateur Clic()



           



           
     



          





    • Partager sur Facebook
    • Partager sur Twitter
      20 juillet 2016 à 22:01:29

      Bonsoir ChristiandeLARMINA


      Je ne peux malheureusement pas t'aider ce soir, mais je peux déjà te donner un conseil pour que les autres personnes sur le forum puissent t'aider plus facilement, quand tu veux envoyer du code, utilise le bouton avec des balises de code (deuxième bouton en partant de la droite).

      Je reviens demain, si quelqu'un ne t'as pas déjà aider ;).

      Salut !

      -
      Edité par Lozul 20 juillet 2016 à 22:02:01

      • Partager sur Facebook
      • Partager sur Twitter
        21 juillet 2016 à 16:57:13

        Merci SejiKage!

        En fait il y aurait deux choses:

        - où  caser quoi en programmation objet

        - Comment récupérer les coordonnées de la souris via la fonction lambda (et quoi mettre dans la fonction lambda?)

        Rien que celà m'aiderait considérablement...

        • Partager sur Facebook
        • Partager sur Twitter
          22 juillet 2016 à 8:52:12

          Bonjour Xn2027

          Pour récupérer les coordonnées de la souris il faut passer par les instructions suivantes:

          from tkinter import *
          
          def click(evt):
          
          	if evt.widget==C:
          		print("Clic gauche sur le canevas")
          	else:
          		print("Clic gauche sur la fenêtre")
          	print("Position: x=", evt.x,"et y=", evt.y)
          
          root = Tk()
          C = Canvas(root, width=50, height=50, bg="green")
          C.place(x=30,y=30)
          root.bind('<ButtonPress-1>', click)
          root.mainloop()

          Explication:

          widget.bind(event, action)

          widget: est le widget sur lequel on surveille l'événement , il peut s'agir d'une fenêtre Tkinter, ou d'un Canvas par exemple;

          event: chaine de caractère représentant le type d’événement à surveiller;

          action: fonction à exécuter lorsque l'événement se produit.

          # -- #

          La fonction doit être déclarée comme demandant un paramètre d'entré:

          def action(evt):
             ...

          evt: donneras diverses informations complémentaires sur l'action réalisée.

          # -- #

          Liste des events: NMT

          Plus d'info et les Event Attributes: effbot.org

          N'hésite pas à demander des éclaircissements ;)

          [Edit]

          Ça m'apprendras à relire avant de poster :honte:, tu fais déjà ça très bien dans ton code original.

          Mais alors pourquoi cette question: "Comment récupérer les coordonnées de la souris via la fonction lambda" ?

          Ensuite, pourrez tu préciser les problèmes que tu rencontre s'il-te-plait ? Je ne peux pas tester ton code (impossible pour moi d'installer PIL sur ma machine actuel), je ne peux donc pas repérer les erreurs

          Par rapport à PIL: je pense que tu devrais lire ce topic -> OC

          P&P (Peace and Python) !



          -
          Edité par Lozul 22 juillet 2016 à 9:08:39

          • Partager sur Facebook
          • Partager sur Twitter
            22 juillet 2016 à 15:24:08

            J'ai testé le code et il m'affiche "Parcelle object has no attribute x" aux lignes 50 et 67, soit dans la fonction CreerImage():

                def __init__(self, master = None):
                    """Constructeur mettant en relief l'évènement Souris"""
                    tk.Frame.__init__(self, master)
                    self.pack()
                    self.CreerImage()

            et ligne 67, dans la fonction CreerImage()

                def CreerImage(self):
            
                    self.canvas = tk.Canvas(self, width=1000, height=800)
                    self.canvas.pack(side='left')
                    self.image = Image.open('parcelles_IX_XVI.jpg')
                    self.photo = ImageTk.PhotoImage(self.image)
            
            
                    self.canvas.create_image(0,0, anchor=tk.NW, image=self.photo)
            # La méthode bind() permet de lier un événement avec une fonction :
            # un clic gauche sur la zone graphique provoquera l'appel de la fonction utilisateur Clic()
            
            
                    self.canvas.bind('<<button1>>', self.Clic)
                    self.canvas.create_rectangle(self.x+r, self.x-r, self.y+r, self.y-r, outline='black',fill='green')

            En fait, en programmation "normale", sans programmation "objet", je veux dire par là sans définir de classe, de constructeur... çà marche.

            Après j'ai bêtement copié-collé un code qui définissait comment ordonner son code en programmation objet, et de là, il se passe deux choses:

            soit le x n'est pas reconnu, soit c'est la fonction event qui est à définir.

            J'espère avoir été assez clair (pour que tu ne perdes pas ton temps à essayer de me comprendre...)

            En gros en programmation classique pas de problème. Mais j'ai lu un tuto "penserentkinter" qui expliquait qu'il fallait mieux faire de la POO.

            Après en python2 il y a tout ce qu'il faut, mais trouver comment faire de la POO tkinter en python3, j'ai l'impression que ce n'est pas simple à trouver. (Mais j'ai du mal regarder...)

            Merci de ton aide



            • Partager sur Facebook
            • Partager sur Twitter
              22 juillet 2016 à 17:11:30

              Le problème est à peu près le même, que tu fasses de la POO ou de la prog classique. Ligne 15 de ton second code, tu utilises les variables self.x et self.y. Or je ne vois nulle part avant leur assignation? Si ton programme fonctionne en prog classique, c'est sûrement parce que tu les as défini AVANT de les utiliser. ;)

              Là où se situe la différence, c'est qu'il faut créer les variables à l'intérieur de la fonction __init__ (c'est pas obligé, mais c'est plus propre de réunir tous les attributs de ton objet au même endroit). Donc ça donnerai quelque chose comme:

              def __init__(self, x, y, master=None, **arguments_parent):
                  super().__init__(master, **arguments_parent)
                  self.x = x
                  self.y = y
                  self.pack()
                  self.CreerImage()
              • Partager sur Facebook
              • Partager sur Twitter
              Précepte: Le mieux est l'ennemi du bien
                22 juillet 2016 à 17:26:44

                Ouf ! Olygrim est dans la place ^^.

                Avant toute choses, j'aimerais savoir où en est-tu dans ton apprentissage de la POO ?

                La POO ne peut pas être juste recopiée, il faut la comprendre (tu me corrigeras si je me trompe), c'est une manière de penser comme quoi Tout est objet, je te renvois au cours d'OC, si besoin, mais je pense que tu l'as déjà lu.

                [2/3]

                J'ai essayé de réorganiser ton code, mais je ne peux toujours pas le tester (lol) donc je ne sais pas ce que ça va donner. Le gist.

                [3/3]

                Je pense avoir lu quelque part que le modules PIl était dépassé depuis Python3 est remplacé par Pillow (cf ce topic)

                -
                Edité par Lozul 22 juillet 2016 à 18:19:51

                • Partager sur Facebook
                • Partager sur Twitter
                  23 juillet 2016 à 13:21:02

                  Je pensais, mais apparamment ce n'est pas le cas, avoir suffisamment potassé le livre de Vincent Le Goff (je cite ma source, pas pour le prendre )àa partie ni le critiquer. Je pense en effet n'avoir pas bien compris certaines choses. Cependant, il bien fallu que je me lance un jour, car c'est en codant que l'on devient codeur. Mais son code était structuré comme ceci, avec les méthodes listées les unes à la suite des autres et non récapitulées dans le constructeur:

                  class TableauNoir():
                      """On définit la classe"""
                      def__init__(self):
                          self.surface = ""
                  #Et ensuite il listait les méthodes:
                      def ecrire(self, message_a_ecrire):
                  #Texte de la méthode
                      def effacer(self):
                  


                  De plus, je n'ai pas vu le mot super(). Pouvez-vous m'expliquer de quoi il retourne? (Encore une fois je trouve le livre lumineux, mais en cherchant des solutions à mes problèmes je tombe sur des codes plus complexes...

                  J'ai tenté d'installer Pillow, sur une linux mint 17.3 en virtual box (comme çà si mon code plante, je n'ai pas à tout réinstaller, juste à refaire une machine virtuelle, c'est un ami informaticien qui m' a conseillé çà). Je n'ai pas vu dans le gestionnaire de logiciels pillow, donc j'ai installé Python3-imagetk ou quelque chose comme çà, qui est un "fork" de pillow. Mais je ne pense pas que ce soit çà qui pose problème.

                  J'ai essayé ton code réorganisé, mais il m'affiche que la méthode clic n'est pas définie (name 'clic' is not defined). C'est là que je ne trouve pas le moyen pour que python retrouve la fonction dès qu'il faut la lier avec un widget. J'ai lu qu'il fallait une fonction lambda...(mais quoi mettre dedans).

                  En fait, je ne pensais pas qu'il fallait faire appel à l'héritage avec la fonction super()!

                  -
                  Edité par Xn2027 23 juillet 2016 à 13:38:15

                  • Partager sur Facebook
                  • Partager sur Twitter
                    24 juillet 2016 à 10:01:42

                    Bonjour Xn2027

                    A-tu essayer de sortir la fonction "clic" de ta "class" ? J'ai tenté la même chose, maisx n'était reconnus comme un attribut deParcelle et je ne sais pas pourquoi ...

                    Voilà, je suis désolé mais je ne vais plus pouvoir t'aider, je dois m'absenter deux semaines

                    P&P !

                    -
                    Edité par Lozul 24 juillet 2016 à 10:02:13

                    • Partager sur Facebook
                    • Partager sur Twitter
                      24 juillet 2016 à 12:05:19

                      Une classe ce n'est pas bien compliqué. C'est un ensemble de fonctions (qu'on appelle méthodes) et de variables (qu'on appelle d'attributs). C'est tout. Autrement dit, c'est juste une façon d'organiser son code. L'avantage, c'est que chaque instance de la classe aura son propre espace des noms (et donc aucun conflit pour deux variables/fonctions qui ont le même nom).

                      Prenons l'exemple suivant en prog "classique":

                      #EN CLASSIQUE
                      
                      #LES FONCTIONS
                      def clic(event, file):
                          global counter
                      
                          x = event.x
                          y = event.y
                          counter += 1
                      
                          r = 20
                          xpr, xmr = x + r, x - r
                          ypr, ymr = y + r, y - r
                      
                          msg = "La zone carrée a pour coordonnées:"
                                "{}, {}, {}, {}".format(xpr, xmr, ypr, ymr)
                                "; Ce carré est le numéro {}".format(counter)
                          print(msg)
                      
                          #Ouverture du fichier
                          with open(file, "a") as f_coord:
                              f_obj.write("{}".format(msg))
                              if (540 < xpr < 570 and 500 < xmr < 540 and 180 < ypr < 220 and
                              155 < ymr < 170):
                                  f_obj.write("Vous êtes dans la parcelle de Lorilloux.")
                              f.write("\n")
                      
                      
                      def creer_image(master, image_path, file, x, y, r):
                          canvas = tk.Canvas(master, width=1000, height=800)
                          canvas.pack(side='left')
                      
                          #Chargement de l'image
                          image = Image.open(image_path)
                          photo = ImageTk.PhotoImage(image)
                          canvas.create_image(x, y, anchor=tk.NW, image=photo)
                      
                          #Association de la fonction clic au bouton gauche de la souris
                          canvas.bind('<button1>', lambda event: clic(event, file))
                      
                          #Création d'un rectangle noir autour d'image
                          canvas.create_rectangle(x + r, x - r, y + r, y - r,
                                                  outline='black', fill='green')
                      
                          #On renvoie le canvas et l'image
                          return canvas, photo
                      
                      
                      #CORPS DU PROGRAMME
                      counter = 0
                      
                      root = tk.Tk()
                      parcelle = tk.Frame(root)  #width? height?
                      parcelle.pack()
                      
                      tk.Button(self, text='Quitter', command=root.destroy).pack(side='bottom')
                      
                      
                      #Création du terrain
                      #Deux variables pour récupérer les références
                      photos, canvas = [], []
                      
                      #Boucle qui va construire le terrain (xc et yc: centre de l'image)
                      for xc in range(20, 620, 40):
                          for yc in range(20, 420, 40):
                              can, pho = creer_image(parcelle, 'parcelles_IX_XVI.jpg', "Coord.txt",
                                                     xc, yc, 20)
                              photos.append(pho), canvas.append(can)


                      En premier on définit les fonctions. Ensuite dans le corps on définit les variables counter, photos et canvas qui sont liées au Frame. Enfin on exécute la boucle principale pour placer chacune des images.

                      Et bien le programme est quasiment le même en POO. Les fonctions sont placées comme méthodes, et les variables comme attributs:

                      #EN POO
                      
                      #LA CLASSE
                      class Parcelle(tk.Frame):
                          def _init__(master, **arguments_parent):
                              super().__init__(master, **arguments_parent)
                              self.counter = 0
                              self.photos = []
                              self.canvas = []
                      
                          def clic(self, event, file):
                              x = event.x
                              y = event.y
                              self.counter += 1
                      
                              r = 20
                              xpr, xmr = x + r, x - r
                              ypr, ymr = y + r, y - r
                      
                              msg = "La zone carrée a pour coordonnées:"
                                    "{}, {}, {}, {}".format(xpr, xmr, ypr, ymr)
                                    "; Ce carré est le numéro {}".format(counter)
                              print(msg)
                      
                              #Ouverture du fichier
                              with open(file, "a") as f_coord:
                                  f_obj.write("{}".format(msg))
                                  if (540 < xpr < 570 and 500 < xmr < 540 and 180 < ypr < 220 and
                                  155 < ymr < 170):
                                      f_obj.write("Vous êtes dans la parcelle de Lorilloux.")
                                  f.write("\n")
                      
                          def creer_image(self, image_path, file, x, y, r):
                              canvas = tk.Canvas(self, width=1000, height=800)
                              canvas.pack(side='left')
                      
                              #Chargement de l'image
                              image = Image.open(image_path)
                              photo = ImageTk.PhotoImage(image)
                              canvas.create_image(x, y, anchor=tk.NW, image=photo)
                      
                              #Association de la fonction clic au bouton gauche de la souris
                              canvas.bind('<button1>', lambda event: clic(event, file))
                      
                              #Création d'un rectangle noir autour d'image
                              canvas.create_rectangle(x + r, x - r, y + r, y - r,
                                                      outline='black', fill='green')
                      
                              #Enregistrement des références
                              self.canvas.append(canvas), self.photos.append(photo)
                      
                      
                      #CORPS DU PROGRAMME
                      root = tk.Tk()
                      parcelle = Parcelle(root)
                      parcelle.pack()
                      
                      tk.Button(self, text='Quitter', command=root.destroy).pack(side='bottom')
                      
                      
                      #Boucle qui va construire le terrain
                      for xc in range(20, 620, 40):
                          for yc in range(20, 420, 40):
                              parcelle.creer_image('parcelles_IX_XVI.jpg', "Coord.txt", xc, yc, 20)




                      J'ai pas testé mes progs, donc il se peut (fortement) qu'il y ait des modifications à faire pour qu'il fonctionnent. Mais l'idée est là. Il n'y a pas beaucoup de différences entre une forme classique et une forme POO. Il faut bien évidemment réorganiser les attributs et rajouter self devant chacun d'eux et le mettre également en 1er paramètre des méthodes, mais si tu as bien construit ton programme il ne devrait pas y avoir énormément de choses à changer ;).

                      PS: Le code que j'ai fait pour la boucle de construction n'est qu'un exemple. Si tu veux que chaque canvas est une image différente, il faudra le modifier en conséquence.

                      -
                      Edité par Olygrim 24 juillet 2016 à 12:57:28

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Précepte: Le mieux est l'ennemi du bien
                        27 juillet 2016 à 17:58:39

                        Merci Olygrim! Cà correspond à mes attentes, mais le code ne "marche pas", et je butte sur un avertissement: il y a un problème de keysim en ligne 43 (entre autres, j'espère réussir à me débrouiller pour le reste).

                        J'avais quelques questions. Manifestement j'ai beaucoup lu sans comprendre, mais parfois le déclic se fait avec des questions "débiles":

                        Pourquoi faire deux attributs d'instance self.photos et self.canvas distincts? Ne peut-on les faire tenir dans un même attribut? Pourquoi ce sont des tableaux? Qu'est-ce qu'une "référence" en python?
                        • Auriez-vous un tutoriel explicitant celà, mais pour Python3 (tout ce que j'ai lu était en python2, et la conversion en python actuel était compliquée).
                        • x, y et r sont définies en ligne 12-13 et 16 dans la méthode clic(), et sont reprises en paramètre de la méthode creer_image(). Comment est-ce possible (ce ne sont pas des attributs de classe!)? Car j'avais compris que quand une variable était définie dans une fonction ou dans une méthode, à moins d'être globale elle n'était pas réutilisable par la suite...

                        Et peut-on faire tenir tout le process dans une seule classe?

                        Merci pour votre disponibilité.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          27 juillet 2016 à 19:09:54

                          Pour le keysim, c'est sûrement parce que ce n'est pas <button1> qu'il faut mettre mais plutôt <Button-1> ou quelque chose comme ça.

                          J'ai fait deux attributs distincts pour illustrer l'exemple, mais rien ne t'empêche de réunir les objets dans un même attribut. Et ce n'est pas des tableaux mais des listes, que j'ai choisi encore une fois pour l'exemple. Libre à toi de choisir un autre conteneur pour conserver tes données.

                          Sauf erreur de ma part, la notion de référence est la même en python2 et en python3. Après ici c'est un abus de langage. Ce que je veux dire c'est qu'on ajoute une référence à l'objet créé (en l'enregistrant dans une variable) pour éviter que python ne supprime l'objet (lorsque plus rien ne fait référence à un objet, python le supprime de lui-même).

                          C'est exact. Une variable créée à l'intérieur d'une fonction (sauf un attribut ou en utilisant global) n'est pas réutilisable à l'extérieur. Ceci dit, dans mon code les variables des lignes 12, 13 et 16 et celles de la ligne 33 sont totalement décorrélées. Dans le cas de creer_image, ce sont des paramètres que je vais utiliser aux lignes 64 et 65 pour placer les images (donc aucun lien avec un quelconque event). Par contre dans le cas de la méthode clic, effectivement c'est lié à un event qui sert juste à comparer la position du curseur avec une zone bien précise de la fenêtre (ligne 28). Ça n'a donc aucun rapport avec le placement de l'image.

                          Concernant le process dans une seule classe, j'aurai tendance à dire que ce n'est pas une bonne construction. Comme dit précédemment, c'est une façon de découper le code (en essayant de réunir des objets ayant un lien entre eux), mais ensuite il faut utiliser cette classe dans une partie plus classique. Une classe doit donc servir à construire un objet et non à contenir tout le programme. ^^

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Précepte: Le mieux est l'ennemi du bien
                            28 juillet 2016 à 13:29:56

                            Merci Olygrim;

                            çà répond grandement à mes questions. J'ai remédié au problème du "keysim", mais maintenant il m'affiche que dans self.canvas.append(canvas) que le parcelle object n'a pas d'attribute canvas (et je suppose que c'est pareil pour self.photos.append(photo). C'est le problème type qui me fait patauger. Aurais-tu une solution?

                            Sinon, à quoi correspond le super() en ligne 6 (je n'ai pas très bien compris à quoi çà correspondait dans la doc python...)? Que sont les arguments parents et le "master"

                            Sinon çà m'aide beaucoup. J'ai juste quelques problèmes avec le débogage.

                            -
                            Edité par Xn2027 28 juillet 2016 à 14:01:33

                            • Partager sur Facebook
                            • Partager sur Twitter
                              28 juillet 2016 à 14:52:02

                              Argh, j'ai effectivement oublié un underscore devant la méthode init (il en faut deux de chaque côté):

                              __init__


                              Concernant le super, c'est une manière plus propre pour faire l'héritage:

                              #Il vaut mieux écrire ceci
                              super().__init__(master, **arguments_parent)
                              
                              
                              #Que cela
                              tk.Frame.__init__(self, master, **arguments_parent)


                              Comme je ne me suis pas encore plongé dans le pourquoi de cette écriture, je ne pourrais pas te donner une bonne raison de l'utiliser. Mais sur le forum, ceux qui sont beaucoup plus calé que moi préconise l'utilisation de super donc je leur fait entièrement confiance ;).

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Précepte: Le mieux est l'ennemi du bien
                                28 juillet 2016 à 17:49:24

                                OK. Cà m'affiche maintenant une TypeError: __init__ recquiert 1 positional argument, 2 were given...

                                Je voulais juste savoir à quoi se référait "master". Sinon il faut que je me renseigne sur les arguments parents (et par la même occasion les kwargs)...

                                -
                                Edité par Xn2027 28 juillet 2016 à 17:53:05

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  28 juillet 2016 à 18:27:34

                                  Le paramètre que j'ai appelé master correspond à la fenêtre dans laquelle va s'afficher le Frame. Dans mon exemple, je l'utilises à la ligne 55 en lui passant en argument l'objet root (qui est une fenêtre Tk).
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Précepte: Le mieux est l'ennemi du bien
                                    28 juillet 2016 à 21:27:15

                                    D'accord, mais pourquoi affiche-t-il un Type Error:__init__ 1 positional argument recquiered, 2 given? Comment corriger celà?

                                    -
                                    Edité par Xn2027 28 juillet 2016 à 21:28:19

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      28 juillet 2016 à 23:20:10

                                      En rajoutant le paramètre self (que j'ai oublié de mettre dans la méthode __init__ :p):

                                      def __init__(self, master, **arguments_parent):
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      Précepte: Le mieux est l'ennemi du bien
                                        29 juillet 2016 à 11:13:52

                                        Maintenant çà met beaucoup de temps à charger pour finir par ne rien afficher et mettre: "processus arrêté" sur le terminal.

                                        J'ai rajouté une fonction pour redimensionner l'image qui était trop grande pour le canvas, mais il n'y a pour le coup plus rien qui ne s'affiche!

                                            def creer_image(self, image_path, file, x, y, r):
                                                canvas = tk.Canvas(self, width=1000, height=800)
                                                canvas.pack(side='left')
                                         
                                                #Chargement de l'image
                                                image = Image.open(image_path)
                                                
                                                #Redimensionnement image
                                                image = image.resize((1000, 800), Image.ANTIALIAS)
                                                photo = ImageTk.PhotoImage(image)
                                                canvas.create_image(x, y, anchor=tk.NW, image=photo)
                                        



                                        Le processus se termine normalement sans que rien ne se soit affiché au final...

                                        A quoi correspond les intervalles que tu as rajouté dans la boucle for?

                                        -
                                        Edité par Xn2027 29 juillet 2016 à 11:16:49

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          29 juillet 2016 à 12:26:44

                                          Ma boucle for n'est qu'un exemple. Le plus important est de comprendre ce que tu as construit.

                                          Tu as construit une classe (nommé Parcelle) qui dérive de la classe Frame. Dans celle-ci, tu as ajouté deux méthodes: creer_image et clic. La première permet de créer un canvas qui contiendra une image. La seconde permet de voir si la position du curseur se trouve dans une zone bien précise.

                                          C'est tout.

                                          C'est donc à toi de voir comment exploiter cette nouvelle classe pour faire le traitement que tu souhaites. Autrement dit, les lignes 53 à 64 de mon code ne sont qu'un exemple d'utilisation de la classe. Tu les supprimes et tu déploies ton propre code pour faire ton propre traitement ;)

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          Précepte: Le mieux est l'ennemi du bien
                                            29 juillet 2016 à 15:47:32

                                            C'est ce que j'avais compris; cependant je n'arrive pas à le faire marcher. Je veux juste faire apparaître l'image, le bouton quitter et qu'un rectangle s'affiche quand je fais un clic gauche dans l'image. Faut-il faire appel à la fonction clic? Dans ce cas il faut que je la redéfinisse complètement...
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              29 juillet 2016 à 16:38:57

                                              Xn2027 a écrit:

                                              Dans ce cas il faut que je la redéfinisse complètement...

                                              Je ne sais pas.

                                              De ce que j'ai compris de ton code, à chaque fois que tu vas créer une image tu vas lier la méthode clic au canvas créé (ligne 43). Donc normalement tu n'as rien de plus à faire, la méthode étant déjà associée au canvas. Il suffit de cliquer gauche sur celui-ci (si Button-1 correspond bien au bouton gauche de la souris) pour exécuter la méthode qui va afficher dans la console un message et qui va l'écrire également dans un fichier.



                                              -
                                              Edité par Olygrim 29 juillet 2016 à 16:40:10

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Précepte: Le mieux est l'ennemi du bien
                                                29 juillet 2016 à 16:47:39

                                                En fait initialement il s'agit d'un script que j'ai trouvé sur internet, qui affiche une image dans un canvas. Quand on clique sur l'image çà affiche un carré à l'endroit où on a cliqué. J'aimerai afficher celà (dans mon cas l'image d'une parcelle forestière) et récupérer les coordonnées du clic et du rectangle (elles seront en pixel, mais je peux les reconvertir par  la suite en métrique) pour les stocker dans un fichier. J'aimerai si possible faire celà en POO. Quand j'essaie ton script, rien ne s'affiche alors qu'à la base il y avait une image dans une frame, et un rectangle qui s'affichait.

                                                Je suis désolé de t'embêter avec ce problème, mais tes explications m'aident beaucoup...

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  29 juillet 2016 à 20:02:08

                                                  Xn2027 a écrit:

                                                  Quand j'essaie ton script, rien ne s'affiche alors qu'à la base il y avait une image dans une frame, et un rectangle qui s'affichait.


                                                  J'ai basé mon programme sur le tien (le 1er message) et normalement il fait la même chose (si je ne me suis pas trompé :p). Dans celui-ci, je ne vois nulle part la création d'un rectangle à l'endroit où l'utilisateur a cliqué. Ni même la récupération des coordonnées du rectangle ou encore la conversion en métrique.

                                                  Xn2027 a écrit:

                                                  En fait, en programmation "normale", sans programmation "objet", je veux dire par là sans définir de classe, de constructeur... çà marche.


                                                  Peut-être que la version POO actuelle n'est pas bonne. Si tu as compris un peu comment ça fonctionnait, tu devrais repartir de la version classique pour construire une nouvelle version POO ^^. Mais garde en tête que la POO n'est pas obligatoire et ne se prête pas forcément à tous les programmes. Si ton code fonctionne bien en version classique, autant la garder et essayer de la perfectionner ;).

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  Précepte: Le mieux est l'ennemi du bien
                                                    29 juillet 2016 à 20:19:12

                                                    OK. Je vais tâcher de retrouver le script et de le bidouiller.

                                                    Merci pour ton soutien et ta disponibilité!

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter

                                                    Structuration image sous tkinter

                                                    × 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