Cannot Display an Image in Tkinter

When I run the program the canvas shows up but the Image does not.

canvas = Canvas(frame, width = 128, height = 128, bg= 'white')
    image_data = Image.open('NoArt.gif')
    ppm_f = ImageTk.PhotoImage(image_data)
    canvas.create_image(0, 0, image = ppm_f, anchor = NW)
    canvas.pack(side=BOTTOM)

any Ideas??

PS.

I have
PIL ver 1.6,
python 2.6, and
The Version of Tkinter that comes with python 2.6

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Ok, I figured It out. Apparently due to the way that python deals with garbage disposal the pictures just get erased. A reference to the image in the global scope is required. This is the working code I eventually ended up using:

self.photo = PhotoImage(file="noart.ppm")
    self.Artwork = Label(self.frame, image=self.photo)
    self.Artwork.photo = self.photo
    self.Artwork.pack()

that self.Artwork.photo = self.photo is the important part. It ensures that the Image will be shown.

Method 2

As mentioned in this very answer and this more popular question & answer and also in effbot.page

When you add a PhotoImage or other Image object to a Tkinter widget,
you must keep your own reference to the image object. If you don’t,
the image won’t always show up.

The problem is that the Tkinter/Tk interface doesn’t handle references
to Image objects properly; the Tk widget will hold a reference to the
internal object, but Tkinter does not. When Python’s garbage collector
discards the Tkinter object, Tkinter tells Tk to release the image.
But since the image is in use by a widget, Tk doesn’t destroy it. Not
completely. It just blanks the image, making it completely
transparent…

The solution is to make sure to keep a reference to the Tkinter
object,

For example the image in below code won’t always show up, if at all as it isn’t declared in global scope:

import tkinter as tk

root = tk.Tk()

def show_image():
    img_label = tk.Label(root)
    image = tk.PhotoImage(file="test.png")
    img_label['image'] = image

    img_label.pack()


show_image()
root.mainloop()

pmby6

whereas in the example below img_label.image is declared globally, as an attribute attached to our very img_label in this example, and will be shown:

import tkinter as tk

root = tk.Tk()

def show_image():
    img_label = tk.Label(root)
    img_label.image = tk.PhotoImage(file="test.png")
    img_label['image'] = img_label.image

    img_label.pack()


show_image()
root.mainloop()

8noyy

It is though still strange as img_label isn’t globally declared either. A less confusing way would be adding global image as the first line to the show_image.

Method 3

If anyone else ever has a similar problem, you can try this hardcoded solution:

import Image
import Tkinter as tk

def cleanhex(x):
    return str(hex(x))[-2:]

def renderimage(target,data,w,h):
    canvas = tk.Canvas(target,width=w,height=h)
    canvas.pack()
    for x in range(w):
        for y in range(h):
            c = "#" + cleanhex(data[x,y][0]) + cleanhex(data[x,y][1]) + cleanhex(data[x,y][2])
            canvas.create_line(x,y,x+1,y+1,fill=c)

im = Image.open("whatever.whatever")
renderimage(root,im.load(),im.size[0],im.size[1])


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x