0

Edit: I've narrowed down the problem to the fact that the code inside the function is not correctly referencing the main canvas widget, but because the function is called via a bind event, I'm not quite sure how to reference the main canvas...(more detail at the bottom)

I am have the following code that displays an image inside a tkinter canvas widget. This is the code for the container creation:

canvas = tk.Canvas(width=640, height=480)
canvas.place(x=50, y=50)
canvas.bind("<B1-Motion>", draw_rectangle)
test_img = ImageTk.PhotoImage(Image.open("test_image.png"))
image_container = canvas.create_image(0, 0, anchor="nw", image=test_img)

This works exactly as expected: the image displays inside the canvas. The next step is to update the image displayed using an opencv image that has a rectangle added, converted to a TkImage, and then handed to the canvas as follows (all of the tutorials I've found use some version of this same methodology). This was done inside a function:

def draw_rectangle(event):
    cv2img = cv2.rectangle(data, pt1=(x1, y1), pt2=(x2, y2), color=(255, 255, 255), thickness=5)
    img = Image.fromarray(cv2img)
    photo_img = ImageTk.PhotoImage(img)
    canvas.itemconfig(image_container, image=photo_img)

The cv2img displays correctly in it's own window if I call:

cv2.imshow("image", cv2img)

...and the Image.fromarray shows correctly in it's own window if I call:

img.show()

Yet when I try to pass the image to the canvas, I just end up with a blank canvas. There are no errors displayed in the console. Any ideas?

P.S. I know that the color channels will be reversed but I haven't swapped them yet as it seemed less of a priority than getting an image to display :)

UPDATE

I neglected a very important piece of the puzzle in my original question. The code to update the canvas is in a function that is called when the mouse button is moved through a binding.

I moved the updated code outside of the function, and it works as expected. But this leads me to a related problem...

Becuase the function is called via an event binding (mouse move) I'm suspect that the "canvas" call inside the function is not pointing towards the canvas created outside the function... but I'm not quite sure how to correct that as the first positional argument needs to the be the event...

I've updated the code above.

Greg Steiner
  • 647
  • 1
  • 9
  • 20
  • Does this answer your question? [Why does Tkinter image not show up if created in a function?](https://stackoverflow.com/questions/16424091/why-does-tkinter-image-not-show-up-if-created-in-a-function). This assumes that the update code is in a function, but the original (working) image is in top-level code (or a main function that contains the mainloop, and therefore continues executing for the entire duration of your GUI). – jasonharper Jan 30 '23 at 05:41
  • That is essentially my problem, but it's unclear how to correct it in my code as of yet. Because I'm not using a class, but it's just a function within my main code, I can't use "self" so I'm still looking for the proper way to retain the reference. – Greg Steiner Jan 30 '23 at 05:53
  • The link shows *lots* of ways of dealing with this. Saving a reference in a global variable, or as an attribute of the Canvas would seem to be the easiest options in your situation. – jasonharper Jan 30 '23 at 05:55
  • I think I follow. I was focusing on the wrong part. If I understand correctly, I need to retain a reference to the IMAGE, not the Canvas object – Greg Steiner Jan 30 '23 at 05:58
  • Was able to make it work using a global variable to hold the most recent image. Thanks for the help! – Greg Steiner Jan 30 '23 at 06:08

0 Answers0