0

I'm working with Python 3.7 and have been trying to get many pictures loaded at the same time while keeping the transparency of those images.

It seemed I had found a way, although I came across a strange (but consistent) behaviour when it came to loading images onto a canvas widget. For the record I use Pillow for that. I can't say that the images don't load, but the problem seems to be that they only load in certain circumstances and those circumstances aren't related to code changes. Hence the title called this behaviour 'strange'.

I stripped down my project to the simplest parts to see if I could get the behaviour to repeat and I can indeed. The code is pretty simple.

Let's start with 'TestClass'. It's just a class with a method that takes a canvas and puts a given image on it:

from PIL import Image, ImageTk
class TestClass():

    def AddImageToCanvas(self, canvas):
        img1 = Image.open('D:\Downloads\Pictures\Python\PNG\\2C.png').convert('RGBA')
        img1 = img1.resize((140, 200), Image.ANTIALIAS)
        pImg1 = ImageTk.PhotoImage(img1)
        canvas.create_image(0, 0, image=pImg1, anchor='nw')

Then we have the main file, which is as follows:

import tkinter as tk
from PIL import Image, ImageTk
import MainDirectory.TestClass as tclass

def AddImageToCanvasMain(canvas):
    img1 = Image.open('D:\Downloads\Pictures\Python\PNG\\QC.png').convert('RGBA')
    img1 = img1.resize((140, 200), Image.ANTIALIAS)
    pImg1 = ImageTk.PhotoImage(img1)
    canvas.create_image(100, 200, image=pImg1, anchor='nw')

root = tk.Tk()
root.geometry("1200x900")

canvasMain = tk.Canvas(root, width=1200, height=900, bg='white')
canvasMain.pack()

tc = tclass.TestClass()
tc.AddImageToCanvas(canvasMain)

AddImageToCanvasMain(canvasMain)

img1 = Image.open('D:\Downloads\Pictures\Python\PNG\\KD.png').convert('RGBA')
img1 = img1.resize((140, 200), Image.ANTIALIAS)
pImg1 = ImageTk.PhotoImage(img1)
canvasMain.create_image(300, 200, image=pImg1, anchor='nw')

root.mainloop()

The purpose of this code is to load an image to the main canvas (canvasMain) in three contexts. The first is in the main execution code. The second is using a method in the main file. The third is using a method in a class. Since I'm calling all three, and each image is in a different location, we should get three images on the canvas right? No. We get one. That would be 'KD' (the King of Diamonds - these are images of cards). Why not the other two? I don't know at the moment.

So what happens if I get rid of that image load part and just leave the method and the class method? I get nothing. Have I tried playing with the coords just to make sure they're on the screen? Yes. In fact I've pasted the king of diamonds image load into the method and the class method, since I know that one works fine.

The next thing you might be wondering is if that other code runs at all. This is where it gets interesting. I started with a break point in the method in the main file (AddImageToCanvasMain). It does run, but the interesting part is this: if I step over the 'create_image' line itself, the image will appear. If I don't step over that line (and I've tried just going as far as the one before), it won't work. I've tried the same in the class method. Further testing showed that, to get the image to appear, I had to stop on the resize line, then step over the ImageTK.PhotoImage line AND the canvas.create_image line for it to work. If I stepped over any less it didn't work. More was fine.

What happens if I step over the relevant lines for the main method and the class method? Then I get all my images as I'd originally intended. But... obviously this isn't a solution since I can't be doing that every time.

What you have above is the entire code. If this is the intended behaviour then I don't understand it. The only thing I've done above just creating a new project is importing Pillow.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685

0 Answers0