Précédent   Forum du club des développeurs et IT Pro > Autres langages > Python & Zope > Contribuez
Contribuez Proposez vos articles, cours, tutoriels, faq, sources pour Python & Zope
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 29/07/2012, 10h52   #1
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
Localisation : France, Hérault (Languedoc Roussillon)

Informations professionnelles :
Activité : Technicien Help Desk, maintenance, réseau, système et +
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2006
Messages : 2 650
Points : 3 776
Points : 3 776
Par défaut [FAQ][Tkinter][Divers] Pourquoi j'obtiens le message _tkinter.TclError: image "pyimage1" doesn't exist ?

Bonjour,

Peut être un rajout à faire dans la FAQ. C'est un basique mais bon...

Citation:
Pourquoi j'obtiens le message _tkinter.TclError: image "pyimage1" doesn't exist ?

Pour commencer une petite explication du fonctionnement de l'instance Image de Tkinter:

Lors de la création d'une première instance Tk celle ci deviens le root par défaut.
Lors d'une création d'une instance Image (instance PhotoImage, BitmapImage ou une instance compatible comme pour ImageTk du module PIL par exemple) celle ci est associée au root par défaut et, si son nom n'est pas spécifié via l'option name, elle est nommée pyimageX (ou X est un nombre incrémenté à chaque création d'instance d'image pour une même instance Tk).
Code :
1
2
3
4
5
6
7
8
9
10
>>> import tkinter
>>> root = tkinter.Tk()
>>> img = tkinter.PhotoImage(file='exemple.gif')
>>> img.name
'pyimage1'
>>> img1 = tkinter.PhotoImage(file='exemple1.gif', name='exemple1')
>>> img1.name
'exemple1'
>>> root.image_names()
'exemple1 pyimage1'
Lorsque vous utilisez l'option image d'un Widget, ou le create_image d'un Canvas, ce n'est pas le nom que vous lui avez donner sous Python qui est gardé en référence mais son nom interne.
Code :
1
2
3
4
5
6
7
8
>>> import tkinter
>>> root = tkinter.Tk()
>>> img = tkinter.PhotoImage(file='exemple.gif')
>>> lab = tkinter.Label(root, image=img)
>>> lab.config('image')
('image', 'image', 'Image', '', 'pyimage1')
>>> lab.cget('image')  # 'pyimage1' et non img
'pyimage1'
C'est ce nom qui est donné lors de l'erreur.

L'erreur image "nom_de_limage" doesn't exist interviens lorsque plusieurs instances Tk sont présentes et que celle à qui l'on fait référence n'est pas celle à qui l'image est associée.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import tkinter
>>> root = tkinter.Tk()
>>> otherroot = tkinter.Tk()
>>> img = tkinter.PhotoImage(file='exemple.gif')
>>> lab = tkinter.Label(otherroot, image=img)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.2/tkinter/__init__.py", line 2462, in __init__
    Widget.__init__(self, master, 'label', cnf, kw)
  File "/usr/lib/python3.2/tkinter/__init__.py", line 1961, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "pyimage1" doesn't exist
>>> otherroot.image_names()
''
>>> root.image_names()
'pyimage1'
Le fait d'avoir plusieurs instances Tk peut avoir deux origines:

- Vous utilisez des instances Tk pour vos fenêtres secondaires et dans ce cas vous devez plutôt utiliser des instances Toplevel pour celles-ci.

- Vous utilisez un IDE écrit avec Tkinter, IDLE par exemple, et le root par défaut est l'instance Tk de votre IDE car c'est la première créée. Dans ce cas vous devez spécifier l'instance Tk à utiliser avec l'option master de l'instance Image:
Code :
1
2
3
4
5
6
>>> import tkinter
>>> root = tkinter.Tk()  # Disons que c'est votre IDE
>>> myroot = tkinter.Tk()
>>> img = tkinter.PhotoImage(file='exemple.gif', master=myroot)
>>> lab = tkinter.Label(myroot, image=img)
>>> lab.pack()
Dans tous les cas l'utilisation des Toplevel pour les fenêtres secondaires et le fait de spécifier l'option master sont des pratiques plus que fortement recommandées.

Note: Cette FAQ ne tiens pas compte du fait que vous devez garder une référence à votre image
Votre avis ?

@+
__________________
Merci d'utiliser le forum pour les questions techniques.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/07/2012, 20h05   #2
wiztricks
Expert Confirmé Sénior
 
Inscription : juin 2008
Messages : 3 739
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 3 739
Points : 4 581
Points : 4 581
Salut,

D'un point de vue technique:
  • à une instance Tk correspond une application TK et un interpréteur TCL,
  • à chaque objet tkinter sera associé à une variable TCL crée dans l'interprêteur correspondant,

Le nom de la variable TCL étant indispensable pour lier l'objet tkinter à "l'objet" TCL correspondant, tkinter devra construire le nom "unique" de la variable TCL associée. De plus, nous avons un nommage hiérarchique pour les widgets et "plat" pour variables, images, commandes,...

Le soucis est que tkinter ne vérifie pas toujours l'existence de la variable TCL avant de passer une commande. TCL ne connaissant que le nom des variables créées par tkinter, il ne pourra pas deviner à quel objet cela correspond. Mais si le nom n'a pas été précisé par l'appelant, ajouter du code pour éviter l'erreur ne sera pas plus lisible.

Au delà des considérations techniques, il y a surtout un problème de "conception" quant à ce qu'on appelle "application".

Associer plusieurs applications Tk à la même application Python (ce qu'on fait en créant plusieurs instances Tk reflète souvent une incompréhension de ce qu'est une instance Tk.

Une fois qu'on a dit çà, il n'y a plus trop de sens à créer le widget d'une application dans une autre...
"default root" est la mécanique qui rend compte de ce cas général: l'application Tk est celle qui a été crée et à l'instant t il y a en 0 ou 1.

tkinter pourrait alerter le débutant en produisant un "warning" lorsqu'il essaie de créer une nouvelle instance Tk sans avoir positionné tk.NoDefautlRoot.

Positionner tk.NoDefaultRoot force l'appelant à préciser le master dans tous les cas, et évite bien des tracas si on doit débugger ce type d'application "particulière".

Le cas général reste quand même d'avoir une application Python pour une application Tk. "default root" ayant été construit pour ne pas avoir (toujours) préciser le master dans ce cas, difficile de recommander le contraire!
Pourquoi ne pas recommander d'appeler tk.NoDefaultRoot avant tout?

- W
__________________
Architectures Post-Modernes
wiztricks est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/07/2012, 20h45   #3
PauseKawa
Expert Confirmé
 
Avatar de PauseKawa
 
Homme Patrice BLANGARIN
Technicien Help Desk, maintenance, réseau, système et +
Inscription : juin 2006
Messages : 2 650
Détails du profil
Informations personnelles :
Nom : Homme Patrice BLANGARIN
Localisation : France, Hérault (Languedoc Roussillon)

Informations professionnelles :
Activité : Technicien Help Desk, maintenance, réseau, système et +
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2006
Messages : 2 650
Points : 3 776
Points : 3 776
Bonjour wiztricks,

Citation:
Envoyé par wiztricks Voir le message
Pourquoi ne pas recommander d'appeler tk.NoDefaultRoot avant tout?
En fait le but était de ne pas aller jusqu’à la tkapp et rester sur quelque chose de 'simple', en donnant les informations 'minimums' pour comprendre l'explication

Ceci dit:
Citation:
Dans tous les cas l'utilisation des Toplevel pour les fenêtres secondaires et le fait de spécifier l'option master sont des pratiques plus que fortement recommandées.
ou tk.NoDefaultRoot ?
Si cela semble 'utile' autant rajouter tk.NoDefaultRoot à la fin mais laisser l'information 'simple', non ?

@+
__________________
Merci d'utiliser le forum pour les questions techniques.
PauseKawa est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/07/2012, 21h03   #4
wiztricks
Expert Confirmé Sénior
 
Inscription : juin 2008
Messages : 3 739
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 3 739
Points : 4 581
Points : 4 581
L'information "simple" est de dire que la création simultanée d'instances tk n'est supportée qu'après un appel tk.NoDefaultRoot().

Dès qu'on se lance dans l'explication du "pourquoi", on n'est plus dans le "simple" mais dans les explications +/- rapides du fonctionnement de tkinter, tk,... qui risquent d''embrouiller le lecteur.
- W
__________________
Architectures Post-Modernes
wiztricks est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 01h46.


 
 
 
 
Partenaires

Hébergement Web