je développe actuellement une interface graphique sur laquelle je mets un bouton parcourir dont je récupère la valeur et importe le .gif selectionné. Voici le code correspondant :
(Je ne vous donne ici que la partie correspondante du code. Si vous voulez le reste, n'hésitez pas a demander.) Cependant, alors que le chemin est forcement bon, j'obtiens l'erreur suivante :
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1538, in __call__
return self.func(*args)
File "C:\Documents and Settings\p047868\Desktop\MGM.py", line 44, in foncimgimport
zonebench.create_image(0,0,image=giftoimport)
File "C:\Python34\lib\tkinter\__init__.py", line 2332, in create_image
return self._create('image', args, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 2323, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: image "C:/Documents and Settings/p047868/Desktop/chien.gif" doesn't exist
Merci d'avance pour vos réponses
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
Mais maintenant j'ai encore pire!!! L'image ne s'affiche toujours pas mais je n'ai plus de message d'erreur (j'ai essayé en changeant les coordonnées, en mettant une height et width,etc...)
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
Mais maintenant j'ai encore pire!!! L'image ne s'affiche toujours pas mais je n'ai plus de message d'erreur (j'ai essayé en changeant les coordonnées, en mettant une height et width,etc...)
C'est pas pire, car ce que tu as modifié sera correct comparé à ta proposition de départ. Maintenant pour ton problème, difficile de dire sans code plus complet.
La documentation mentionne Notez qu’il est nécessaire de conserver une référence vers cette valeur qu'on peut traduire dans le code par:
def foncutils(event):
global giftoimports
x,y=event.x,event.y
if x<530 and x>30 and y<110 and y>50:
giftoimport = askopenfilename(filetypes = [("Images GIF","*.gif")])
giftoimports = PhotoImage(file=giftoimport)
zonebench.create_image(250,250,image=giftoimports)
Plus propre serait d'associer la référence de l'objet PhotoImage au widget qui l'exploite, afin de ne pas polluer l'espace de nom du module et ainsi ce passer définitivement de l'instruction global.
def funcutils(event):
if 30 < x < 530 and 50 < y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
zonebench._image_ref = image = PhotoImage(file=name)
zonebench.create_image(250,250,image=image)
Plus propre serait d'associer la référence de l'objet PhotoImage au widget qui l'exploite, afin de ne pas polluer l'espace de nom du module et ainsi ce passer définitivement de l'instruction global.
def funcutils(event):
if 30 < x < 530 and 50 < y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
zonebench._image_ref = image = PhotoImage(file=name)
zonebench.create_image(250,250,image=image)
Si c'est pour créer à la volée un attribut protégé depuis une fonction qui n'est même pas méthode de classe, mieux vaut garder global.
Il n'y a pas de considération public/private en Python. Un underscore seul devant un nom signifie simplement, par convention, que l'élément est à usage interne. Libre à celui qui veut de l'exploiter en connaissance de cause.
Si dans l'exemple j'ai appliqué cette convention c'est uniquement parce que visiblement cette référence n'est pas utilisée ailleurs et que par habitude j'ai tendance à classer les variables qui ne sont pas utile à l'extérieur de leur objet comme des éléments internes.
Si dans l'exemple j'ai appliqué cette convention c'est uniquement parce que visiblement cette référence n'est pas utilisée ailleurs et que par habitude j'ai tendance à classer les variables qui ne sont pas utile à l'extérieur de leur objet comme des éléments internes.
C'est bien le problème puisque vous écrivez cela non pas dans une méthode de classe mais dans une fonction externe. Puis vous racontez que polluer un objet de type instance serait plus propre que de polluer un objet de type module: c'est pas très cohérent.
IdiotBête_ a écrit:
Il n'y a pas de considération public/private en Python. Un underscore seul devant un nom signifie simplement, par convention, que l'élément est à usage interne. Libre à celui qui veut de l'exploiter en connaissance de cause.
Le PEP8 défini très bien ces conventions et sont pythoniques les constructions qui les respectent.
Pour informations, en Python, les variables globales n'existent pas (et ce par construction et non par convention).
Les variables globales existent, non par construction ou par convention, mais par déclaration à l'aide du mot clé global.
Mais finalement on s'en tape un peu car comme dit plus haut se sont des conventions et non des normes... L'essentiel à retenir ici, c'est que le PO qui est débutant ne doit pas avoir comme exemple l'utilisation du mot clé global, car après il risquera des débordements liés à sa mauvaise utilisation.
Pas que ce mot clé soit interdit ou banni, mais parce-que le PO en fera une utilisation catastrophique.
L'essentiel à retenir ici, c'est que le PO qui est débutant ne doit pas avoir comme exemple l'utilisation du mot clé global, car après il risquera des débordements liés à sa mauvaise utilisation.
Qui êtes vous pour décider de ce de ce qu'on peut/doit montrer ou pas aux débutants?
On peut espérer qu'un débutant progresse et apprenne un jour la POO et sera raisonnable quant à l'utilisation des variables globales (qui n'ont rien à voir avec le mot clé global)...
On ne va pas tourner en rond sur cette histoire de convention, suffit de renommer la variable si tu estimes qu'elle a un usage externe. Ceci dit, j'insiste, il n'est absolument pas question d'attribut privé, c'est une notation pour indiquer aux utilisateurs du code que l'élément à un usage interne et qu'il faut faire attention - connaître le code - si on veut l'utiliser pour autre chose sans casser le code.
Ranger la référence de l'image dans l'instance du widget qui l'exploite est plus propre que de créer une variable globale (ou variable/attribut de module si tu préfères) depuis une fonction. Ajouter des attributs d'instances à la volé est une pratique parfaitement pythonic et cela permet d'organiser proprement les éléments au-lieu de tout mettre en vrac dans le scope global du module.
Je ne vais pas relancer la discussion sur l'instruction global dont l'usage correct est encore plus rare que celui de la fonction exec, pour ne pas dire totalement évitable... Faites comme vous voulez, et ne venez pas vous plaindre des effets de bord et des longues heures de debogage qu'elle vous imposera.
L'essentiel à retenir ici, c'est que le PO qui est débutant ne doit pas avoir comme exemple l'utilisation du mot clé global, car après il risquera des débordements liés à sa mauvaise utilisation.
Qui êtes vous pour décider de ce de ce qu'on peut/doit montrer ou pas aux débutants?
Une personne expérimentée sur les forums voyant régulièrement les codes massacrés par ce mot clé... Il peut y avoir des exceptions et pourquoi pas un ou deux débutants utilisant avec parcimonie global, mais c'est tellement rare !
Sinon, je ne suis pas le seul et des gens bien plus compétents et expérimentés à présenter ce mot clé comme le diable incarné du langage.
Pour moi c'est une erreur de conception, pour d'autres, les inconvénients sont bien plus nombreux. Ce mot clé a plus tendance à être une rustine qu'un besoin réel à la résolution d'un problème.
Pour moi c'est une erreur de conception, pour d'autres, les inconvénients sont bien plus nombreux. Ce mot clé a plus tendance à être une rustine qu'un besoin réel à la résolution d'un problème.
Quand comprendrez vous que les variables globales n'existent pas en Python. Il n'y a donc pas de global state. Sûr que tant que vous ne l'aurez pas compris, vous allez sauter au plafond quand vous verrez le mot clef global quitte à le remplacer par quelque chose qui n'est pas mieux.
Imaginez que j'ai écrit:
image = [ None]
def funcutils(event):
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
image[0] = PhotoImage(file=name)
zonebench.create_image(250,250,image=image[0])
Ne parlons pas de variables globales si ça te gêne tant, mais simplement du mot clé global qui déclare une variable comme modifiable dans un environnement local telle une fonction... Il en reste pas moins que cette possibilité n'est pas naturelle, tu es d'accord ? Tu devrais en tout cas, sinon pourquoi doit-on y ajouter ce mot clé ?
Je vais reprendre une phrase lors d'une réponse sur un forum,
Use of global variables is a consequence of your program’s design. Overuse of globals is a symptom of poor design. Almost any use of the global keyword in Python is an indication of poor design.
Pour ton code,
Je préfère l'utilisation des dictionnaires avec comme clé la chaîne de caractères représentant le nom de l'image et comme valeur l'objet image créé par PhotoImage, car en général sur un canvas, on y place de multiples images.*
À part ce mot clé je reste tout de même assez ouvert à partir du moment où le code fait le café
Ne parlons pas de variables globales si ça te gêne tant, mais simplement du mot clé global qui déclare une variable comme modifiable dans un environnement local telle une fonction... Il en reste pas moins que cette possibilité n'est pas naturelle, tu es d'accord ? Tu devrais en tout cas, sinon pourquoi doit-on y ajouter ce mot clé ?
C'est vous qui avez des problèmes avec le mot clef global. Et vous ne réalisez même pas que c'est de la pure forme car je pourrait aussi bien écrire:
import __main__ as ns
def funcutils(event):
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
ns.image = PhotoImage(file=name)
zonebench.create_image(250,250,image=ns.image)
voire:
import sys as ns
def funcutils(event):
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
ns.image = PhotoImage(file=name)
zonebench.create_image(250,250,image=ns.image)
qui sont des horreurs j'en conviens.
Mais vous ne vous rendez pas compte que ce que vous proposez:
def funcutils(event):
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
zonebench.image = PhotoImage(file=name)
zonebench.create_image(250,250,image=zonebench.image)
Ça me choque pas, la doc indique que ça peut être utile... mais je peux comprendre que cela peut être déroutant dans une lecture de code et quelque fois même nuisible. Si on peut éviter c'est mieux !
Après, convaincre que cette solution est bonne, n'est pas simple, mais convaincre que global n'est pas une solution, ça l'est !
Ça me choque pas, la doc indique que ça peut être utile... mais je peux comprendre que cela peut être déroutant dans une lecture de code et quelque fois même nuisible. Si on peut éviter c'est mieux !
Après, convaincre que cette solution est bonne, n'est pas simple, mais convaincre que global n'est pas une solution, ça l'est !
Pourtant il n'y a pas de différences entre:
import __main__ as ns
def funcutils(event):
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
ns.image = PhotoImage(file=name)
zonebench.create_image(250,250,image=ns.image)
et:
def funcutils(event):
global image
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
image = PhotoImage(file=name)
zonebench.create_image(250,250,image=image)
on crée le même attribut image dans le module courant... en utilisant ou pas le mot clef global.
Dans le 2ème cas on ne crée pas, on déclare un changement d'état pour une variable immutable
Pourtant on crée une variable dans le même espace de noms (celui du module), c'est juste la méthode qui change. C'est juste la méthode qui change... Et aussi la fixation que vous avez le le mot clef global.
Lorsqu'on assigne un objet à un attribut (avec le signe =), on réalise ce que Python appelle le binding/association entre un nom et un objet dans un espace de noms désigné (par ns.) ou prédéfini côté noms simples. C'est l'objet qui peut être mutable, pas l'association.
Tiens encore une façon de tourner la chose sans global:
def funcutils(event):
if 30 < event.x < 530 and 50 < event.y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
image = globals()['image'] = PhotoImage(file=name)
zonebench.create_image(250,250,image=image)
Et si vous en avez marre des espaces de noms, vous avez aussi cette possibilité là:
def funcutils():
image = None
def closure(canvas, x, y):
nonlocal image
if 30 < x < 530 and 50 < y < 110:
name = askopenfilename(filetypes=[("Images GIF","*.gif")])
image = PhotoImage(file=name)
canvas.create_image(250,250,image=image)
return closure
× 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.
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin
"Je ne crois qu'en une seule chose : le pouvoir de la volonté humaine." - Joseph Stalin