IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tkinter Python Discussion :

Cliquer sur des photos miniatures à l'aide d'un gestionnaire d'événements


Sujet :

Tkinter Python

  1. #1
    Membre à l'essai Avatar de Kaa'dem-2072
    Homme Profil pro
    Biogärtner
    Inscrit en
    Décembre 2015
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Biogärtner
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2015
    Messages : 24
    Points : 18
    Points
    18
    Par défaut Cliquer sur des photos miniatures à l'aide d'un gestionnaire d'événements
    Bonjour à tous,

    Je me permets de vous contacter car je suis confronté à un problème que je comprends mais que je n'arrive pas à résoudre. J'ai créé un petit programme pour gérer mon jardin et j'y ai inclu une photothèque contenant des photos miniatures que je veux agrandir grâce à une fonction (event). Je n'ai pas encore rédigé la fonction d'agrandissement mais peu importe : je teste le fonctionnement du gestionnaire d'événements en changeant le fond bleu des canevas qui contiennent chaque photo en un fond rouge lorsque la souris les survole.

    J'ai donc créé une boucle for in range(0, len(...)) et un tag_bind() afin que lorsque je survole la photo, mon curseur de souris se transforme en main et le contour de la photo devienne rouge.

    Mon problème, c'est que ça fonctionne uniquement avec la dernière photo. C'est comme si, à chaque itération, ma boucle détruisait le tag_bind() et ne conservait que le dernier tag_bind() pour la dernière photo.

    Voici mon code et en dessous une capture d'écran de mon programme. Quelque soit la photo que je survole avec ma souris, c'est toujours la dernière qui s'active (couleur rouge).

    Comment puis je faire pour pouvoir activer ma fonction(event) sur chaque photo séparément? Je cherche encore et encore mais je bloque

    Je ne sais pas si j'ai été très clair dans mes explications mais je remercie par avance ceux qui m'apporteront leur aide.

    Nom : prog.png
Affichages : 190
Taille : 57,6 Ko

    Nom : phototheque.png
Affichages : 206
Taille : 543,1 Ko

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Ton "self.can3.tag_bind(....)" ne survit qu'au dernier objet, donc la dernière image.

    Puisque tu fais de la programmation objet alors crée un objet Image avec ses propres attributs dont, entre autres, le "tag_bind".

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Python est un langage interprété. Et cela a des conséquences!
    Si on écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> def f(): print(a)
    ...
    La variable "a" n'a pas besoin d'exister lorsqu'on définit la fonction "f".
    Par contre, si on l'exécute sans avoir définit "a", çà va raler:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> f()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in f
    NameError: name 'a' is not defined
    >>>
    autrement dit, on va accéder à la variable lors de l'execution de la fonction.
    Dans votre code c'est plus compliqué car vous créez les fonctions dans une boucle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> fcts = []
    >>> for x in range(3):
    ...     a = x
    ...     def f():
    ...         print(a)
    ...     fcts.append(f)
    ...
    mais on récupèrera toujours la dernière valeur de "a".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> fcts[0]()
    2
    >>> fcts[1]()
    2
    >>> fcts[2]()
    2
    Pour s'en sortir, on gèle une copie de "a" dans les paramètres par défaut:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    >>> for x in range(3):
    ...     a = x
    ...     def f(a=a):
    ...        print(a)
    ...     fcts.append(f)
    ...
    Ca donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> fcts[3]()
    0
    >>> fcts[4]()
    1
    >>> fcts[5]()
    2
    >>>
    Cela explique pour quoi la fonction agrandir fonctionne ainsi...

    Après, si vous voulez faire des choses compliquées avec tkinter, il faut prendre le temps d'apprendre à s'en servir.
    Pourquoi écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def agrandir(event):
         self.can3.configure(...)
    alors que le "canvas" en question est dans event.widget!!!
    Vous pourriez écrire plus simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def agrandir(event):
         event.widget.configure(...)
    Et comme agrandir sait récupérer le widget, plus besoin de définir autant de fonctions que de widgets...

    De même, pourquoi fabriquer un Canvas pour chaque Photo transformée en Button (via tag_bind)? Button(image=...) le fait aussi bien en moins de lignes. Et pour récupérer la photo ou le Button, il faut regarder côté "closures".

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre à l'essai Avatar de Kaa'dem-2072
    Homme Profil pro
    Biogärtner
    Inscrit en
    Décembre 2015
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Biogärtner
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2015
    Messages : 24
    Points : 18
    Points
    18
    Par défaut Merci
    Citation Envoyé par VinsS Voir le message
    Salut,

    Ton "self.can3.tag_bind(....)" ne survit qu'au dernier objet, donc la dernière image.

    Puisque tu fais de la programmation objet alors crée un objet Image avec ses propres attributs dont, entre autres, le "tag_bind".


    Un grand merci Vincent car tu m'as mis sur la piste. J'ai donc repris mon code et créé des objets images. Maintenant, ça fonctionne. Je peux cliquer sur n'importe quelle image et j'obtiens le résultat escompté :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class Agrandir(object) :
    	def __init__(self, can2, image, i) :
    		self.can2 = can2
    		self.image = image	
    		self.i = i
    	def agrandir(self) :
    		self.size = 256, 256
    		self.image.thumbnail(self.size)
    		self.photo = PIL.ImageTk.PhotoImage(self.image)
    		self.can3 = Canvas(self.can2, height = 260, width = 200, bg = 'blue', bd = 1, highlightthickness=1)
    		self.can3.grid(row=1, column = self.i, padx=10, sticky='n')			
    		self.can3.create_image(1, 1, anchor='nw', image=self.photo, tag = 'agrandir')
    		self.can3.tag_bind('agrandir', "<Enter>", lambda event : self.can3.config(bg='red', cursor='hand2'))
    Création des objets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    self.fichier = open('photos_serre_2', 'r')
    		self.inserer_photos = self.fichier.readlines()
    		for i in range (0, len(self.inserer_photos)) :
    			self.image = PIL.Image.open(self.inserer_photos[i].strip())
    			self.photo = Agrandir(self.can2, self.image, i)
    			self.photo.agrandir()
    Bonne journée à toi.

  5. #5
    Membre à l'essai Avatar de Kaa'dem-2072
    Homme Profil pro
    Biogärtner
    Inscrit en
    Décembre 2015
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Biogärtner
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2015
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Salut Wiztricks,

    Merci pour ta réponse,

    Quand tu dis "si tu veux faire des choses compliquées avec Tkinter, il faut prendre le temps de s'en servir"...

    Je suis bien conscient que mon code est loin d'être parfait. Seulement, l'informatique n'est pas mon métier. C'est juste une passion.
    J'ai découvert le langage python fin 2015 grâce au livre de Gérard Swinnen et depuis, je code tous les jours. Je parcours beaucoup les forums mais j'essaie dans la mesure du possible de poser une question uniquement lorsque je suis vraiment dans une impasse. Je crois bien que c'est seulement la deuxième fois que je demande un renseignement sur ce forum.

    Malgré ses imperfections, j'utilise mon programme tous les jours pour "gérer" les récoltes de mon jardin. C'est pas vraiment utile à vrai dire. Mais ça m'amuse.

    Merci en tout cas pour tes remarques que je vais prendre en compte.

  6. #6
    Membre à l'essai Avatar de Kaa'dem-2072
    Homme Profil pro
    Biogärtner
    Inscrit en
    Décembre 2015
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Biogärtner
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2015
    Messages : 24
    Points : 18
    Points
    18
    Par défaut Petite précision
    @ Wiztricks


    Je précise que la fonction pour agrandir les photos n'est pas encore rédigée. Pour l'instant, j'utilise juste une expression lambda dans la méthode de la classe Agrandir avec un changement de couleurs pour tester si ça fonctionne.
    Et maintenant que ça fonctionne, je pense que je vais utiliser le widget Top level pour l'agrandissement de chaque photo.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Citation Envoyé par Kaa'dem-2072 Voir le message
    Quand tu dis "si tu veux faire des choses compliquées avec Tkinter, il faut prendre le temps de s'en servir"...

    Je suis bien conscient que mon code est loin d'être parfait. Seulement, l'informatique n'est pas mon métier. C'est juste une passion.
    Que ce soit par passion ou par nécessité alimentaire, quitte à passer du temps à faire quelque chose autant essayer de le faire bien.


    Citation Envoyé par Kaa'dem-2072 Voir le message
    Je parcours beaucoup les forums mais j'essaie dans la mesure du possible de poser une question uniquement lorsque je suis vraiment dans une impasse. Je crois bien que c'est seulement la deuxième fois que je demande un renseignement sur ce forum.
    Il n'est pas très futé d'apprendre seul dans son coin: vous allez passer beaucoup de temps à faire tomber un truc en marche. Vous serez ravi que çà fonctionne mais vous risquez de vous enfermer dans de mauvaises pratiques. Vous avez deux solutions, lire le code écrit par d'autres (mais c'est pas facile) ou poser des questions dans des forums.
    note: les forums sont là pour vous essayer de vous éclairer sur des concepts pas facile à piger ou des détails pas facile à réaliser. Et tant que vous ne demandez pas qu'on code à votre place, de bonnes volontés essaieront de vous aider.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre à l'essai Avatar de Kaa'dem-2072
    Homme Profil pro
    Biogärtner
    Inscrit en
    Décembre 2015
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Biogärtner
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2015
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    @ Wiztricks,

    Oui mais d'une certaine manière, je ne suis pas vraiment seul dans mon coin. Si je ne pose pas beaucoup de questions dans les forums, c'est aussi parce que je trouve très souvent réponse à mes questions. Le forum de développez.com me plaît bien mais ma retenue vient aussi du fait que c'est un site pour les développeurs professionnels, ce que je ne suis pas.

    Cela dit, je vais suivre votre conseil et poser plus de questions. Dans les réponses, je constate qu'il y a souvent différentes approches et ces différents points de vue sont intéressants aussi bien pour moi-même que pour d'autres.

    J'ai viré mes canevas contenant les photos pour les transformer en boutons. Vous constatez donc que je prends en compte ce qu'on me dit!
    Lorsque je clique sur la photo miniature, ça ouvre une fenêtre Toplevel contenant le canevas contenant la photo (cf code et capture d'écran ci-dessous)

    Du coup, j'aurais une autre question. Est-il possible d'ajuster automatiquement un canevas à la taille d'une photo avec les paramètres width et height?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Agrandir(object) :
    	def __init__(self, can2, image, image2, i) :
    		self.can2 = can2
    		self.image = image	
    		self.image2 = image2
    		self.i = i
    	def agrandir(self) :
    		self.size = 256, 256
    		self.image.thumbnail(self.size)
    		self.photo = PIL.ImageTk.PhotoImage(self.image)
    		self.mini_photo = Button(self.can2, height=260, width=200, bg='white', bd=0, image=self.photo, activebackground='green', cursor='hand2', command=self.photo_agrandie)
    		self.mini_photo.grid(row=1, column = self.i, padx=10, sticky='n')
     
    	def photo_agrandie(self) :
    		self.grande_photo = Toplevel(height=600, width = 600)
    		self.size2 = 512, 512
    		self.image2.thumbnail(self.size2)
    		self.photo2 = PIL.ImageTk.PhotoImage(self.image2)
    		self.can3 = Canvas(self.grande_photo, height = 510, width = 375, bg = 'blue')
    		self.can3.grid()
    		self.can3.create_image(1,1, anchor = 'nw', image = self.photo2)


    Nom : phototheque.png
Affichages : 231
Taille : 824,2 Ko

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par Kaa'dem-2072 Voir le message
    Du coup, j'aurais une autre question. Est-il possible d'ajuster automatiquement un canevas à la taille d'une photo avec les paramètres width et height?
    canvas.configure(width=..., height=...) devrait le faire mais plus simple serait de créer un Label(image=...) qui s'ajustera aux dimensions de la photo (comme un Button en fait) - et qui devrait aussi ajuster les dimensions du Toplevel qui le contient.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  10. #10
    Membre à l'essai Avatar de Kaa'dem-2072
    Homme Profil pro
    Biogärtner
    Inscrit en
    Décembre 2015
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Biogärtner
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2015
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    canvas.configure(width=..., height=...) devrait le faire mais plus simple serait de créer un Label(image=...) qui s'ajustera aux dimensions de la photo (comme un Button en fait) - et qui devrait aussi ajuster les dimensions du Toplevel qui le contient.

    - W
    Le widget Label et la fenêtre Toplevel sans aucun paramètre de largeur et de hauteur, ça fonctionne nickel!
    Bonne journée.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	def photo_agrandie(self) :
    		"Méthode permettant d'agrandir les photos"
    		self.grande_photo = Toplevel()
    		self.photo2 = PIL.ImageTk.PhotoImage(self.image2)
    		self.label_photo = Label(self.grande_photo, image = self.photo2)
    		self.label_photo.grid()

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [GD] Bannière "vendu" sur des photos
    Par boblastar69 dans le forum Bibliothèques et frameworks
    Réponses: 1
    Dernier message: 21/02/2008, 00h22
  2. Comment cliquer sur des clips générés par actionscript
    Par ar vuzhugenn dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 04/01/2008, 11h02
  3. Quel logiciel pour écrire sur des photos ?
    Par philippe du web dans le forum Imagerie
    Réponses: 26
    Dernier message: 29/12/2006, 15h25
  4. [WD9] Cliquer sur des enregistrements dans une table
    Par oz80 dans le forum WinDev
    Réponses: 2
    Dernier message: 15/12/2005, 20h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo