3

Here is part of my code called within a function:

#Labels and Window layout
lsfpy = Tk()
lsfpy.title("Helicopters Sydney")
lsfpy.resizable(False, False)
Label(lsfpy, text="Locations in Sydney").grid(row=0)
Label(lsfpy, text="To").grid(column = 1, row=1, sticky=N)
Label(lsfpy, text="From").grid(column = 1, row=2, sticky = W)
Label(lsfpy, text="").grid(column = 1, row=3)
Label(lsfpy, text="Date").grid(column = 1, row=4, sticky=SW)
Label(lsfpy, text="Time").grid(column = 1, row=5, sticky=SW)

#Map
photo = PhotoImage(file = 'GUI Files/Map/Sydmap.gif')
photo = photo.subsample(2)
lbl = Label(lsfpy,image = photo)
lbl.grid(column=0, row=3)

When I run it, I get this error:

    Exception in Tkinter callback
    Traceback (most recent call last):
    File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1702, in __call__
    return self.func(*args)
  File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 22, in calculateandnext
    saveandgotomapf(tp,am1,am2,am3,am4,am5)
  File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 55, in saveandgotomapf
    locationfreight(fdpy)
  File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Locationfreight.py", line 192, in locationfreight
    lbl = Label(lsfpy,image = photo)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2763, in __init__
    Widget.__init__(self, master, 'label', cnf, kw)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2296, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "pyimage4" doesn't exist

When I comment out

 photo = photo.subsample(2)

The error slightly changes to:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1702, in __call__
    return self.func(*args)
  File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 22, in calculateandnext
    saveandgotomapf(tp,am1,am2,am3,am4,am5)
  File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 55, in saveandgotomapf
    locationfreight(fdpy)
  File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Locationfreight.py", line 192, in locationfreight
    lbl = Label(lsfpy,image = photo)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2763, in __init__
    Widget.__init__(self, master, 'label', cnf, kw)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2296, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "pyimage3" doesn't exist

If I copy the code snippet into a new file, there are no problems.

What is causing these errors?

  • Please create a [mcve], right now, your code is partial. We need to be able to reproduce your issue, so you'll need to include all the imports and create a smallest possible example that still raises that exception. – Taku Jul 07 '18 at 05:47
  • Plus, why don't you just import the py file? Why `exec`? (At the very least you can use `execfile()` instead) – Taku Jul 07 '18 at 05:51
  • @abccd I have removed the execs, still get same problem –  Jul 07 '18 at 07:22

1 Answers1

2

In your recent edit, you mentioned the code was in a function, that made all the difference.

The PhotoImage is not kept by tkinter, so you must keep a reference to it before Python's garbage collector gobbles up the image after the function returns. When it does, tkinter couldn't find your image anymore, thus your error saying that the image doesn't exist.

As recommended if effbot, you can do:

photo = PhotoImage(file = 'GUI Files/Map/Sydmap.gif')
photo = photo.subsample(2)
lbl = Label(lsfpy,image = photo)
lbl.image = photo
lbl.grid(column=0, row=3)

You must keep a reference to the image object in your Python program, either by storing it in a global variable, or by attaching it to another object.

Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget. To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:

label = Label(image=photo)
label.image = photo # keep a reference! label.pack()
Taku
  • 31,927
  • 11
  • 74
  • 85
  • Where is the best place to keep the extra reference to the image object? It keeps getting garbage collected when its within the function. –  Jul 08 '18 at 02:24
  • 2
    It's in the answer: `lbl.image = photo` – Taku Jul 08 '18 at 03:51