ythy / blog

Give everything a shot
6 stars 0 forks source link

TKinter image doesn't display #302

Open ythy opened 4 years ago

ythy commented 4 years ago
def create_canvas(self):
    self.canvas = Canvas(self)
    self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9)
    photo = ImageTk.PhotoImage(Image.open('bg.png'))
    self.canvas.create_image(100, 100, image=photo, state=NORMAL)
    self.canvas.create_rectangle(50, 25, 150, 75, fill="red")

上述代码,会导致图片显示空白,应当如下书写:

def create_canvas(self):
    self.canvas = Canvas(self)
    self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9)
    self.photo = ImageTk.PhotoImage(Image.open('bg.png'))
    self.canvas.create_image(100, 100, image=self.photo, state=NORMAL)
    self.canvas.create_rectangle(50, 25, 150, 75, fill="red")

原因:原文

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 by attaching it to a widget attribute:

photo = PhotoImage(...)

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()
Ahmed-E-86 commented 1 year ago

I was pulling my hair off trying to figure this out. Thank you so much.

George-Seletski commented 1 year ago

Thanks dude!

heer-s-mehta commented 1 year ago
def create_canvas(self):
    self.canvas = Canvas(self)
    self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9)
    photo = ImageTk.PhotoImage(Image.open('bg.png'))
    self.canvas.create_image(100, 100, image=photo, state=NORMAL)
    self.canvas.create_rectangle(50, 25, 150, 75, fill="red")

上述代码,会导致图片显示空白,应当如下书写:

def create_canvas(self):
    self.canvas = Canvas(self)
    self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9)
    self.photo = ImageTk.PhotoImage(Image.open('bg.png'))
    self.canvas.create_image(100, 100, image=self.photo, state=NORMAL)
    self.canvas.create_rectangle(50, 25, 150, 75, fill="red")

原因:原文

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 by attaching it to a widget attribute:

photo = PhotoImage(...)

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

thankyou so much

Gabriel-522277 commented 11 months ago

Hello everybody, I have the same problem with displaying a PhotoImage in a Label, which remains black (background color). The problem is the same if I try to display on a Canvas (with create_image). I'm unable to understand what is wrong in these lines. Can someone explain my mistake to me ? Thanks a lot in advance !

from tkinter import *
root = Tk()
root.geometry("532x700")
img = PhotoImage("D:/PHOTOS/Flo.png")
lblAffich = Label(root, image = img, bg="black")
lblAffich.image = img       # according to that was explained in a previous comment
lblAffich.place(x=10,y=10, width=512, height=512)
root.mainloop()
To-mos commented 5 months ago

Hello everybody, I have the same problem with displaying a PhotoImage in a Label, which remains black (background color). The problem is the same if I try to display on a Canvas (with create_image). I'm unable to understand what is wrong in these lines. Can someone explain my mistake to me ? Thanks a lot in advance !

from tkinter import *
root = Tk()
root.geometry("532x700")
img = PhotoImage("D:/PHOTOS/Flo.png")
lblAffich = Label(root, image = img, bg="black")
lblAffich.image = img         # according to that was explained in a previous comment
lblAffich.place(x=10,y=10, width=512, height=512)
root.mainloop()

My version required this for Labels instead lblAffich.configure(image=img)

Gabriel-522277 commented 5 months ago

For my photo-oriented script, it was easier to use pygame. The image is therefore displayed in a pygame window, separate from tkinter.

from tkinter import *
# from PIL import Image, ImageTk    # according to what you need 
import pygame as pg
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (150,0)
    # to constrain pygame window position 
size = 400      # pygame window is a square
root = Tk()
root.geometry(f"100x100+0+0")
pg.init()
fenPg = pg.display.set_mode((size, size))   # init pygame display
file = "D:/PHOTOS/FireWorks.jpg"            # jpg path
# im = Image.open(file)             # if you need EXIF
# imex = im.getexif()

surfImg = pg.image.load(file).convert()
dx, dy = surfImg.get_size() # tuple (width, height)

            #   Scaling to fit the image in the window
if dx > dy:     #   Horizontal format
    dx2 = size;     dy2 = dy * size / dx
else:           #   Vertical format
    dy2 = size;     dx2 = dx * size / dy
surfImg = pg.transform.scale(surfImg, (dx2, dy2))

            #   Displaying
fenPg.blit(surfImg, (0, 0))
pg.display.flip()

root.mainloop()
the-rahulpatel commented 2 months ago
def create_canvas(self):
    self.canvas = Canvas(self)
    self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9)
    photo = ImageTk.PhotoImage(Image.open('bg.png'))
    self.canvas.create_image(100, 100, image=photo, state=NORMAL)
    self.canvas.create_rectangle(50, 25, 150, 75, fill="red")

上述代码,会导致图片显示空白,应当如下书写:

def create_canvas(self):
    self.canvas = Canvas(self)
    self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9)
    self.photo = ImageTk.PhotoImage(Image.open('bg.png'))
    self.canvas.create_image(100, 100, image=self.photo, state=NORMAL)
    self.canvas.create_rectangle(50, 25, 150, 75, fill="red")

原因:原文

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 by attaching it to a widget attribute:

photo = PhotoImage(...)

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

Legend. How did you find this solution since I spent a good chunk of time searching for an answer online?

Gabriel-522277 commented 2 months ago

Thanks a lot for your answer ! With a .png file, your code works very well. Unfortunately, my images are Jpeg. With this sort of files, I get a TclError : couldn't recognize data in image file "D:/PHOTOS/1 IMG_0098.jpg" I tried to : from PIL import Image, ImageTk but I don’t understand how to use these modules.

Anyway, thanks a lot for your help ! !

Gabriel

De : Rahul Patel Envoyé le :samedi 4 mai 2024 11:08 À : ythy/blog Cc : Gabriel-522277; Comment Objet :Re: [ythy/blog] TKinter image doesn't display (#302)

def create_canvas(self): self.canvas = Canvas(self) self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9) photo = ImageTk.PhotoImage(Image.open('bg.png')) self.canvas.create_image(100, 100, image=photo, state=NORMAL) self.canvas.create_rectangle(50, 25, 150, 75, fill="red") 上述代码,会导致图片显示空白,应当如下书写: def create_canvas(self): self.canvas = Canvas(self) self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9) self.photo = ImageTk.PhotoImage(Image.open('bg.png')) self.canvas.create_image(100, 100, image=self.photo, state=NORMAL) self.canvas.create_rectangle(50, 25, 150, 75, fill="red") 原因:原文 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 by attaching it to a widget attribute: photo = PhotoImage(...)

label = Label(image=photo) label.image = photo # keep a reference! label.pack() Legend. How did you find this solution since I spent a good chunk of time searching for an answer online? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>

Gabriel-522277 commented 2 months ago

Hello ! Sorry for my first answer, your corrections work very well ! First, I got around the problem using Pygame. I prefer your idea, because I like understanding the reasons of mistakes. Thanks a lot !

Gabriel

De : Rahul Patel Envoyé le :samedi 4 mai 2024 11:08 À : ythy/blog Cc : Gabriel-522277; Comment Objet :Re: [ythy/blog] TKinter image doesn't display (#302)

def create_canvas(self): self.canvas = Canvas(self) self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9) photo = ImageTk.PhotoImage(Image.open('bg.png')) self.canvas.create_image(100, 100, image=photo, state=NORMAL) self.canvas.create_rectangle(50, 25, 150, 75, fill="red") 上述代码,会导致图片显示空白,应当如下书写: def create_canvas(self): self.canvas = Canvas(self) self.canvas.place(x=0, y=0, relheight=0.9, relwidth=0.9) self.photo = ImageTk.PhotoImage(Image.open('bg.png')) self.canvas.create_image(100, 100, image=self.photo, state=NORMAL) self.canvas.create_rectangle(50, 25, 150, 75, fill="red") 原因:原文 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 by attaching it to a widget attribute: photo = PhotoImage(...)

label = Label(image=photo) label.image = photo # keep a reference! label.pack() Legend. How did you find this solution since I spent a good chunk of time searching for an answer online? — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>