1

I'm trying to get an image on a tkinter canvas to dynamically resize along with the main window. The canvas area is expanding as I have used .pack(fill='both', expand=True) .

I have seen a similar example using a label widget. Similarly, I'm trying to bind canv_1.bind("<Configure>", resize_image)

Due to some error, the image is not visible on canvas. I can get the image to load only if the binding event is removed.

import tkinter as tk
from PIL import Image, ImageDraw, ImageFont, ImageTk
from tkinter import ttk

window = tk.Tk()
window.title("viewer Sample")
window.minsize(300, 225)

frm_Main = tk.Frame(master=window,
                   bg='#1f1e1e',
                   relief=tk.GROOVE,
                   borderwidth=2)


frm_Main.pack(fill='both', expand=True)                  

canv_1 = tk.Canvas(master=frm_Main)
canv_1.pack(fill='both', padx=10, pady=10, expand=True)
img2 = Image.open("beach.jpg")
img_c= ImageTk.PhotoImage(img2)
image_on_canvas= canv_1.create_image(0, 0, image=img_c, anchor='nw')

def resize_image(event):
    new_width = event.width
    new_height = event.height
    print(new_height)
    img3 = img2.resize((new_width,new_height), Image.ANTIALIAS)
    photo1 = ImageTk.PhotoImage(img3)
    canv_1.itemconfig(image_on_canvas, image =photo1 )

canv_1.bind("<Configure>", resize_image)  # load image only when commenting this out


#Main loop
window.mainloop()
rush dee
  • 304
  • 1
  • 4
  • 13
  • As @jizhihaoSAMA suggested below, the addition line `canv_1.image = photo1' fixed the problem. – rush dee Apr 28 '20 at 00:02
  • @Bryan_Oakley Although the solution of the problem is same as another post, the question purpose is different. So marking this as a duplicate won't do any benefit. This post could be value adding to a user who is after information on dynamically resize canvas items. The solution, ie addressing the garbage collection, wasn't apparent when posting the original question. Since the main program consists with event bindings, file load, resize the issue could be anything among those. – rush dee Apr 28 '20 at 00:09

1 Answers1

1

You are nearly close.In the effbot document.

<Configure>: The widget changed size (or location, on some platforms). The new size is provided in the width and height attributes of the event object passed to the callback.

After you bind <Configure> event for your widget,it will call the resize_image function when you run this code.(I guess that's because tkinter will draw the image on the canvas,so the width and the height of the canvas will be changed.)

And also refer this question,That's why your image will disappear.You need to keep a reference in the function to prevent python Garbage Collection.

In the function resize_image:

def resize_image(event):
    .......
    photo1 = ImageTk.PhotoImage(img3)
    canv_1.image = photo1
    canv_1.itemconfig(image_on_canvas, image =photo1)
jizhihaoSAMA
  • 12,336
  • 9
  • 27
  • 49