Ouvrir une image en cliquant sur une image (Python-Tkinter)

Résolu/Fermé
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020 - 8 avril 2020 à 17:11
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020 - 30 avril 2020 à 13:21
Bonjour, j'ai un projet à réaliser en ISN pour le BAC, et je suis bloqué à une étape. Je dois créer une fenêtre dans laquelle plusieurs images sont disposées. Cette étape est déjà faite (voir screen)
Et maintenant, je dois de faire en sorte que ces images soient cliquables et qu'elles renvoient une nouvelle image. Je ne vois pas du tout comment faire ... Merci à tous ceux qui répondront et qui m'aiderons je l'espère.
Bonne journée à vous

A voir également:

35 réponses

Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
8 avril 2020 à 20:47
Bonsoir MrLemon,

Tu as cherché dans la doc Tkinter ?

Tu y verrais que l'on peut récupérer les coordonnées d'un clic de souris sur un 'canvas'

C'est un début, à toi d'imaginer la suite … :-)

Une doc sympa:

https://www.inforef.be/swi/download/apprendre_python3.pdf
2
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
16 avril 2020 à 13:41
ok

la solution n'est pas compliquée puisqu'on récupère les coordonnées du clic et qu'on sait à quel endroit on a placé les images :

can.create_image(50,0, ……)

donc on peut en déduire quelle image on a cliqué …
1
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
16 avril 2020 à 17:01
Merci beaucoup de votre aide, je regarde ça dès que je peux ! :)
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
Modifié le 19 avril 2020 à 11:48
Bonjour MrLemon,

Alors, si tu veux ouvrir une seconde fenêtre, il ne suffit pas de créer un autre Canvas
Un Canvas n'est qu'une zone graphique dans une fenêtre pour dessiner ou afficher des images

De plus pourquoi faire un "bind" de clic de souris une fois de plus: tu veux re cliquer et afficher une 3eme image ?

Voici une ébauche de code que tu peux récupérer et tester, je pense que ca correspond à ce que tu veux faire, je crée une 2eme fenêtre ici: fenetre_2 = Toplevel(fenetre_princ)
Dis moi si ça marche !

# -*- coding:Latin-1 -*-

from tkinter import *

def pick_souris(event):
 global img2

 for k in range(len(images)):
  x1 = images[k][2][0]
  y1 = images[k][2][1]
  x2 = images[k][2][2] + x1
  y2 = images[k][2][3] + y1
  image_2 = images[k][1]

  if(event.x >=x1 and event.x <=x2 and event.y >=y1 and event.y <=y2):
   fenetre_2 = Toplevel(fenetre_princ)
   fenetre_2.geometry('420x350+350+200')
 
   can2 = Canvas(fenetre_2,bg='ivory',height=w_height-70,width=w_width-30)
   can2.place(x = 15,y = 15)
 
   img2 = PhotoImage(file=image_2)
   can2.create_image(10,10,anchor = NW, image=img2)

w_width=420
w_height = 350

fenetre_princ = Tk()
fenetre_princ.title('Test')
fenetre_princ.geometry(str(w_width)+'x'+str(w_height)+'+250+100')

can = Canvas(fenetre_princ,bg='ivory',height=w_height-70,width=w_width-30)
can.place(x = 15,y = 15)
can.bind("<Button-1>", pick_souris)

#Image initiale: taille = 365x212
images = {0:('Fresque_01.png','Fresque_02.png',(10,10,365,212))}

img = PhotoImage(file=images[0][0])
can.create_image(images[0][2][0],images[0][2][1],anchor = NW, image=img)

fenetre_princ.mainloop()
1
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
19 avril 2020 à 15:09
Déjà, lignes 25 et 26, 2 variables pour définir la taille de la fenêtre principale, comme ça, il suffit de changer ces valeurs pour ajuster selon ce que l'on veut

Ensuite, on crée la fenêtre principale et son Canvas que l'on place à x15, y15

Ligne 37: définition d'un dictionnaire "images", si tu ne sais pas ce que c'est qu'on dictionnaire Python, regarde la doc dont je t'ai donné le lien le 8 avril, tu dois comprendre exactement ce que c'est

Ca permet d'avoir un tableau avec les images et leurs coordonnées et donc, en balayant tous ses éléments avec une boucle sur le nombre d'éléments, on évite d'écrire 50 fois
img = PhotoImage(…………
can.create_image(……………
pour chaque photo, comme tu l'a fait au début

J'aurais donc pu écrire la ligne 40 comme ceci:
for k in range(len(images)):
	img = PhotoImage(file=images[k][0])
	can.create_image(images[k][2][0],images[k][2][1],anchor = NW, image=img)


Et dans la fonction "pick_souris", on fait aussi une boucle pour tester sur quelle image on a cliqué, c'est quand même plus pratique et plus court que de faire çà autant de fois qu'il y a d'images

Donc, le dictionnaire un peu plus complet commencerait comme ceci:
images = {0:('Fresque_01.png','Fresque_02.png',(10,10,365,212)), 1:('Fresque_03.png','Fresque_04.png',(375,10,360,210)), 2:  etc .................}


Chaque élément est séparé par une virgule, et composé comme ça:
clé : liste contenant 2 chaines de caractères et une liste
La clé est un peu le numéro d'ordre, ca commence à 0
Les 2 chaines sont la 1ere image, puis celle qui doit la remplacer
La liste contient les coordonnées pour placer la 1ere image, puis sa longueur et largeur

Il faut donc compléter ce dictionnaire avec toutes tes images, leur vrai nom, et leurs vraies coordonnées et tailles, moi, j'ai mis des noms au hasard et les tailles de mes images pour tester
1
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
19 avril 2020 à 16:15
Et si j'ai bien compris, pour rajouter chaque images, il faut rajouter par exemple avec l'image 3 et 4 :
image_3 = images [k][2]
en dessous de
 image_2 = images[k][1]

Puis
img3= PhotoImage(file=image_3)
   can2.create_image(580,0,anchor = NW, image=img3)
en dessous de
img2 = PhotoImage(file=image_2)
   can2.create_image(50,0,anchor = NW, image=img2)


Et
1:('Fresque_03.png','Fresque_04.png',(580,0,250,150))


Si ce n'est pas ça pouvez me le faire pour l'image 3 et 4 pour que je vois et comprenne ? Merci et excuse moi de vous prendre autant de temps.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
27 avril 2020 à 11:52
Bonjour MrLemon,

Je vais te tirer les oreilles :-) :-)
tu n'as pas fait ce que j'ai expliqué dans mes réponses !

Il est bien trop long ton programme : pourquoi créer le dictionnaire images avec les 20 images, si c'est pour ensuite écrier 20 fois can.create_image ….

Si ta boucle ne marche pas, c'est parce que les 2 lignes pour créer l'image ne sont pas indentées : donc elles ne sont pas dans la boucle, donc la boucle tourne à vide et ensuite on créé une seule image : la dernière car i est le dernier indice de la boucle qui vient de finir !

Regarde ce code, fais en un copié/collé et essaie: ca marche parfaitement bien avec la boucle qui balaye le dictionnaire images et il est 3 fois plus court que le tien:
(OK, moi je n'ai que 2 images, mais ca ne change rien au principe)

# -*- coding:Latin-1 -*-
# Affichage d'images	19/04/2020 16:12:36

from tkinter import *

def clic_souris(event):
	''' Si clic de souris sur une image existante
	    ouverture d'une autre fenetre et affichage d'une autre image '''

	global image, fenetre_secondaire

	for k in range(len(images)):
		x1 = images[k][2][0]
		y1 = images[k][2][1]
		x2 = x1 + images[k][2][2]
		y2 = y1 + images[k][2][3]
		image_remplacante = images[k][1]

		if(event.x >=x1 and event.x <=x2 and event.y >=y1 and event.y <=y2):
			#Detruire la fenetre secondaire précédente si elle existe
			if('fenetre_secondaire' in globals()): fenetre_secondaire.destroy()

			fenetre_secondaire = Toplevel(fenetre_princ)
			fenetre_secondaire.geometry('420x350+350+200')
	
			zone_graphique_secondaire = Canvas(fenetre_secondaire,bg='ivory',height=w_height-15,width=w_width-15)
			zone_graphique_secondaire.place(x = 5,y = 5)
	
			image = PhotoImage(file=image_remplacante)
			zone_graphique_secondaire.create_image(10,10,anchor = NW,image=image)

w_width=760
w_height = 350

fenetre_princ = Tk()
fenetre_princ.title('Test')
fenetre_princ.geometry(str(w_width)+'x'+str(w_height)+'+250+100')

zone_graphique = Canvas(fenetre_princ,bg='ivory',height=w_height-15,width=w_width-15)
zone_graphique.place(x = 5,y = 5)
zone_graphique.bind("<Button-1>", clic_souris)

#Image initiales
images = {0:('Fresque_01.png','Fresque_02.png',(10,10,365,212)), 1:('Fresque_03.png','Fresque_04.png',(380,10,365,212))}
img = {}
for k in range(len(images)):
	img[k] = PhotoImage(file=images[k][0])
	zone_graphique.create_image(images[k][2][0], images[k][2][1], anchor = NW, image=img[k])

fenetre_princ.mainloop()

1
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
27 avril 2020 à 13:25
Merci, je fais avec mes connaissances et je fais de mon mieux pour comprendre car on n'avait jamais vu ça auparavant :)
La fenêtre quand on clique dessus n'a pas la même taille qu'avant, pourtant je n'ai pas changé ses dimensions ... Merci encore
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
9 avril 2020 à 11:47
Merci je regarde ça et je vous tiens au courant si j'ai encore quelques problèmes ! :)
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
15 avril 2020 à 11:56
Coucou MrLemon,

As-tu résolu ton problème ?

:-)
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
16 avril 2020 à 12:55
Non pas encore, je me suis pas encore mis dedans, j'avais d'autres devoirs à faire. Je vous tiens au courant si j'ai des problèmes :)
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
16 avril 2020 à 18:09
J'ai réussis à faire quelque chose, il me manque juste à trouver, quand le clic est fait dans une zone définie, il faudrait que cela ouvre une autre image. Merci encore pour votre aide et bonne soirée à vous :)
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
16 avril 2020 à 19:23
Oui, on sait sur quelle image on a cliqué, puisqu'on connait sa position

can.create_image(50,0, ……) et ce point est en haut à gauche (Anchor = NW), et si on connait la

largeur et la hauteur de l'image en pixels, on peut avoir les coordonnées du point en bas à droite

Ensuite on peut tester :

if(event.x in range (x1,x2) and event.y in range(y1, y2)):
can.create_image( avec la nouvelle image)

Par contre ne met pas de photos de ton code, mais copie-le ici et utilise les balises:
https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
16 avril 2020 à 20:50
Je test ça merci !
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
16 avril 2020 à 21:07
Pour x1,x2,y1 et y2 j'imagine qu'il faut les définir avant ? Et pour ce qui est du can.create_image( avec la nouvelle image) il me met "expected an indented block" j'ai essayé plusieurs façon de mettre l'image mais impossible, de plus, il ne veut pas se mettre au même niveau que le print ( c'est à dire décalé d'un cran avec if. Merci encore
0
Bonjour MrLemon,

x1, y1 sont les coordonnées de la position de l'image initiale (donc du point en haut à gauche de l'image initiale), et x2, y2 les coordonnées du point en bas à droite de l'image, et donc si le clic de souris est compris dedans, c'est qu'on a cliqué l'image en question

Il faut donc initialiser tout çà pour chaque image initiale en début de programme, évidement

"expected an indented block" signifie bloc indenté attendu: tu n'as pas mis d'indentation au début de ton instruction qui est surement dans une fonction

En python, il faut respecter çà, et toujours mettre la même indentation partout : si c'est 4 espaces, c'est 4 espaces partout, dans les fonction tests, boucles …

Peux-tu, s'il te plait, copier/coller ton code ici, en ajoutant les balises, comme je te l'expliquais plus haut ? On y verrai plus clair

Merci
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
17 avril 2020 à 14:56
Dites moi si vous voyez le message car ça fais 3 fois que je le poste mais je ne le vois pas ...
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
17 avril 2020 à 15:54
je vois ce message de 14h56:

"Dites moi si vous voyez le message …"
0
Hello MrLemon,

Alors, où en est-tu ? :-)
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
18 avril 2020 à 11:48
Bonjour à vous, tout d'abord merci pour votre aide qui est très précieuse car je ne suis pas très fort en python. J'ai fais quelques tests en définissant x1,y1 et x2,y2 mais cela me fais une erreur. Voici mon programme avec les balises :

 from tkinter import *


fenetre = Tk()
label = Label(fenetre)
label.pack()



fenetre.title ("La fresque du climat - I.Les définitions")
windows_resolution = (1600,1200)
can= Canvas(fenetre,width=1600, height=1200)


photo = PhotoImage(file="Fresque_01.png")
can.create_image(50,0, anchor=NW, image=photo)


photo2 = PhotoImage(file="Fresque_03.png")
can.create_image(580,0, anchor=NW, image=photo2)


photo3 = PhotoImage(file="Fresque_05.png")
can.create_image(0,160, anchor=NW, image=photo3)


photo4 = PhotoImage(file="Fresque_07.png")
can.create_image(50,320, anchor=NW, image=photo4)


photo5 = PhotoImage(file="Fresque_09.png")
can.create_image(50,650, anchor=NW, image=photo5)

photo6 = PhotoImage(file="Fresque_11.png")
can.create_image(315,0, anchor=NW, image=photo6)


photo7 = PhotoImage(file="Fresque_13.png")
can.create_image(840,0, anchor=NW, image=photo7)


photo8 = PhotoImage(file="Fresque_15.png")
can.create_image(400,320, anchor=NW, image=photo8)


photo9 = PhotoImage(file="Fresque_17.png")
can.create_image(0,480, anchor=NW, image=photo9)


photo10 = PhotoImage(file="Fresque_19.png")
can.create_image(360,160, anchor=NW, image=photo10)


photo11 = PhotoImage(file="Fresque_21.png")
can.create_image(400,650, anchor=NW, image=photo11)


photo12 = PhotoImage(file="Fresque_23.png")
can.create_image(1100,0, anchor=NW, image=photo12)


photo13 = PhotoImage(file="Fresque_25.png")
can.create_image(1100,320, anchor=NW, image=photo13)


photo14 = PhotoImage(file="Fresque_27.png")
can.create_image(360,480, anchor=NW, image=photo14)


photo15 = PhotoImage(file="Fresque_29.png")
can.create_image(710,480, anchor=NW, image=photo15)


photo16 = PhotoImage(file="Fresque_31.png")
can.create_image(1100,650, anchor=NW, image=photo16)


photo17 = PhotoImage(file="Fresque_33.png")
can.create_image(1050,160, anchor=NW, image=photo17)


photo18 = PhotoImage(file="Fresque_35.png")
can.create_image(750,320, anchor=NW, image=photo18)


photo19 = PhotoImage(file="Fresque_37.png")
can.create_image(710,160, anchor=NW, image=photo19)


photo20 = PhotoImage(file="Fresque_39.png")
can.create_image(1050,480, anchor=NW, image=photo20)


photo21 = PhotoImage(file="Fresque_41.png")
can.create_image(750,650, anchor=NW, image=photo21)
x1= 50
y1= 0
x2=250
y2= 150
def souris(event):
    if event.x in range(x1, x2) and event.y in range(y1, y2):
        can.create_image(file="Fresque_41.png")



can.bind("<Button-1>", souris)


Label(fenetre).pack()
can.pack()
fenetre.mainloop()




Merci encore pour votre aide ! :)
0
Phil_1857 Messages postés 1883 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 178
18 avril 2020 à 12:18
OK, mais dans ta fonction "souris", si tu veux afficher une image, il faut faire exactement comme pour les autres images:
photo=PhotoImage(………...)
can.create_image(……………...)

(je ne vois pas pourquoi tu fais différemment)

def souris(event):
    if event.x in range(x1, x2) and event.y in range(y1, y2):
        photo21 = PhotoImage(file="Fresque_41.png")
        can.create_image(50,0, anchor=NW, image=photo21)



Enlève les lignes 94 et 95 puisque l'image doit être affichée avec la fonction

J'ai mis 50,0 comme coordonnées puisque tu veux remplacer l'image initiale par celle-ci
(si j'ai bien compris le problème initial)
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
18 avril 2020 à 21:16
Merci, le problème c'est que rien ne se passe quand je clique sur l'endroit défini... Le problème initial est de cliquer sur une image et quand celle ci est cliqué, il doit apparaître une seconde fenêtre
can= Canvas(fenetre,width=1600, height=1200)
et dans cette fenêtre doit être disposé une autre image que celle qui à été cliqué avant. Merci et bonne soirée à vous
x1= 50
y1= 0
x2=250
y2= 150
def souris(event):
    if event.x in range(x1, x2) and event.y in range(y1, y2):
        can= Canvas(fenetre,width=1600, height=1200)
        photo22 = PhotoImage(file="Fresque_02.png")
        can.create_image(800,600, anchor=NW, image=photo22)
        can.bind("<Button-1>", souris)
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
19 avril 2020 à 13:05
Merci ! C'est exactement ce que je cherchais ! Il me reste plus qu'à modifier pour que ce programme intervienne sur toutes les images . Si jamais je n'y arrive pas je me redirigerai vers vous. Pouvez m'expliquer à quoi sert les principales lignes ? J'aimerais comprendre pour pouvoir l'expliquer plus tard, si cela ne vous dérange pas. Merci infiniment et bonne journée à vous :)
0
MrLemon Messages postés 74 Date d'inscription mercredi 8 avril 2020 Statut Membre Dernière intervention 24 mai 2020
19 avril 2020 à 15:58
Super merci beaucoup ! J'ai déjà modifier les tailles ect .. Manque plus qu'à le refaire pour chaque images ! :) Encore une petite question sur les lignes 15, 17 et 28 :
Pourquoi rajoutons nous +350+200 ? (ligne 15)
Pareil pour la ligne 28 (+250+100)
Et qu'est ce que représente ligne 17 :
    can2 = Canvas(fenetre_2,bg='ivory',height=w_height-70,width=w_width-30)

Le "height=w_height-70,width=w_width-30)"
Merci encore
0