2

For fun, I'm creating a crappy helicopter/flappybird clone using tkinter and I've run into some really bizarre behavior with regards images apparently not showing up.

(btw, using python3)

So I started with the following code just to see if I could start getting things to draw:

from tkinter import *
from PIL import ImageTk

class Bird(object):
    def __init__(self, canvas, x=0, y=0):
        self.canvas = canvas
        photo = ImageTk.PhotoImage(file="flappy.gif")
        self.bird = self.canvas.create_image(x,y,image=photo)

class Environment(Canvas):
    def __init__(self, master, width=500, height=500):
        super(Environment, self).__init__(master, width=width, height=height)
        self.pack()
        self.master = master
        self.bird = Bird(self)

if __name__=="__main__":
    r = Tk()
    env = Environment(r)
    env.pack()
    r.mainloop()

Image didn't appear, all I had was a blank canvas. I thought this was odd, so I started playing around to see why that might be the case. My next step was to test that I knew how to create images, so I just made my file a basic image create:

if __name__=="__main__":
    r,c=get_canv()
    c.pack()
    img = ImageTk.PhotoImage(file="flappy.gif")
    c.create_image(100,100,image=img)
    r.mainloop()

And this, predictably, works fine. So, my syntax in the prior code seemed to be correct. This is when I stumbled on something a little confusing:

if __name__=="__main__":
    r,c=get_canv()
    c.pack()
    c.create_image(100,100,image=ImageTk.PhotoImage(file="flappy.gif"))
    r.mainloop()

This didn't draw. I'm left with a blank canvas again. This is what made me suspect that maybe there was some weird threading issue going on behind the scenes. Does Anyone know why the second snippet worked and the third snippet failed?

1 Answers1

3

I've seen this a number of times already. The problem is that the PhotoImage is garbage collected even though it is used in the Label! To fix the problem, just bind it to a member variable of the GUI itself:

self.photo = ImageTk.PhotoImage(file="flappy.gif")
self.bird = self.canvas.create_image(x,y,image=self.photo)

The reason it works in your second example is that the img variable exists until after the mainloop method has finished, while in your third example, it exists only during the creation of the Label.

Community
  • 1
  • 1
tobias_k
  • 81,265
  • 12
  • 120
  • 179