Python Forum
[Tkinter] canvas image problem
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] canvas image problem
#1
Hi,

The (abbreviated) code below does exactly what it is supposed to do.
-Open an image
-resize it
-show it on canvas

But it shows no picture. I have found that this could be because of the garbage collector
that takes the picture away before it can be shown. Some say it is a tkinter "bug".

I can see it should work perfectly, if I add a last line that makes the program crash, e.g.
some operation with a non existant variable ! Now it shows the image!

I read that you must "hold on" to the picture by attaching it to something, like "label.image= img."
But I have no label, and neither "root", nor "canvas" have an .image property;
What to do ?
Paul

 img = Image.open(foto)
 resized_img = img.resize((newW,newH),Image.LANCZOS)
 show_img =ImageTk.PhotoImage(resized_img)      
 x_offset = int((1700-newW)/2)
 canvas.create_image(x_offset,0, image=show_img, anchor = NW)
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#2
This works

#! /usr/bin/env python3

import tkinter as tk

root = tk.Tk()
my_img = tk.PhotoImage(file='icons/ratt.png')
my_img.img = my_img

resized_img = my_img.subsample(2,2)
canvas = tk.Canvas()
canvas.create_image(root.winfo_reqwidth(), root.winfo_reqheight()/2, image=resized_img)
canvas.pack()
root.mainloop()
This works as well

#! /usr/bin/env python3

import tkinter as tk
from PIL import Image, ImageTk

root = tk.Tk()
my_img = (Image.open('icons/ratt.png'))
resized_img = my_img.resize((120,120), Image.LANCZOS)
new_img = ImageTk.PhotoImage(resized_img)
canvas = tk.Canvas()
canvas.create_image(root.winfo_reqwidth(), root.winfo_reqheight()/2, image=new_img)
canvas.pack()
root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#3
OK, I will study those.
All in all, there is virtually no difference between the second example and mine.

I have not tried the subsample one.
Will do, and report back.
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply
#4
Please provide runnable examples. The posted code does not work at all and the missing parts are probably the cause of the problems you are seeing.

I wrote this code that opens a .png file, resizes and draws the image. Looks a lot like your code and it works perfectly.
from PIL import Image, ImageTk
import tkinter as tk

root = tk.Tk()
img = Image.open('dice6.png')
resized_img = img.resize((100, 100), Image.LANCZOS)
show_img = ImageTk.PhotoImage(resized_img)

canvas = tk.Canvas(root, width=200, height=200)
canvas.pack()
canvas.create_image(100, 100, image=show_img)
root.mainloop()
This code looks the same to the unwary eye, but it does not display the image.
from PIL import Image, ImageTk
import tkinter as tk

def get_image(filename):
    img = Image.open(filename)
    resized_img = img.resize((100, 100), Image.LANCZOS)
    show_img = ImageTk.PhotoImage(resized_img)
    return show_img

root = tk.Tk()
canvas = tk.Canvas(root, width=200, height=200)
canvas.pack()
canvas.create_image(100, 100, image=get_image('dice6.png'))
root.mainloop()
This demonstrates what you are calling the "tkinter bug". This is not really a bug, but a result of tkinter being such a thin Python wrapper over Tk. tkinter unloads the responsibility of maintaining image references on the programmer. When you draw an image on the canvas, tkinter passes along the image ID and DOES NOT keep a reference. If you delete your only reference to the image the Python garbage collector sees the reference count drop to zero and the object memory is recycled. The reason the first example displays an image and the second doesn't is because the variables that reference the image in the second example are local to the function. These are deleted when the function exits leaving the image with nobody referencing it, and Python recycles the image.

You can stuff a reference anywhere, but it is best if the holder is related to the image. In this example I am going to fix the problem by adding an "image" attribute to the canvas that displays the image.
from PIL import Image, ImageTk
import tkinter as tk

def get_image(filename):
    img = Image.open(filename).resize((100, 100), Image.LANCZOS)
    return ImageTk.PhotoImage(img)

root = tk.Tk()
canvas = tk.Canvas(root, width=200, height=200)
canvas.pack()
canvas.image = get_image('dice6.png')  # Make sure you don't overwrite a real attribute.
canvas.create_image(100, 100, image=canvas.image)
root.mainloop()
I could keep the image in a global variable or a class variable or a list or a dictionary or a ...

If this information does not solve your problem please post a more complete example.
Reply
#5
Hi,

Thanks for all the help. I wish the tkinter docs would explain things better.
I now understand why the image is disappearing.

So it seems I can stuff the reference anywhere.
My photoImage is called "show_img", just adding
root.img = show_img
does the trick, and I don't have to change anything.
Thx,
Paul
It is more important to do the right thing, than to do the thing right.(P.Drucker)
Better is the enemy of good. (Montesquieu) = French version for 'kiss'.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to resize image in canvas tkinter samuelmv30 2 17,818 Feb-06-2021, 03:35 PM
Last Post: joe_momma
  Problem about image and button scotesse 5 3,005 Apr-27-2020, 10:09 AM
Last Post: scotesse
  [Tkinter] Resizing image inside Canvas (with Canvas' resize) Gupi 2 25,119 Jun-04-2019, 05:05 AM
Last Post: Gupi
  Canvas refreshing problem Faruk 2 2,483 Dec-04-2018, 08:52 AM
Last Post: Faruk
  [Tkinter] Problem loading an image from directory into a Canvas object tiotony 3 3,873 Sep-02-2018, 06:47 PM
Last Post: woooee
  Problem with pygame not switching the mouse image Mondaythe1st 6 6,768 Jul-26-2017, 10:53 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020