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

Contribuez Python Discussion :

[FAQ][Tkinter][Divers] Pourquoi j'obtiens le message _tkinter.TclError: image "pyimage1" doesn't exist ?


Sujet :

Contribuez Python

  1. #1
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 725
    Points : 4 005
    Points
    4 005
    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...

    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : 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
    >>> 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 242
    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 242
    Points : 36 699
    Points
    36 699
    Par défaut
    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.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert confirmé Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 725
    Points : 4 005
    Points
    4 005
    Par défaut
    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:
    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.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 242
    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 242
    Points : 36 699
    Points
    36 699
    Par défaut
    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.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 14
    Dernier message: 08/01/2013, 23h36
  2. Réponses: 2
    Dernier message: 06/07/2012, 20h38
  3. Réponses: 5
    Dernier message: 30/01/2009, 13h00
  4. [VB.Net] Pourquoi ai-je un message "Syntax error in INSERT TO statement" ?
    Par Kropernic dans le forum Accès aux données
    Réponses: 2
    Dernier message: 24/07/2006, 14h26

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