pythonfunctiontkinterphotoimage

Python tkinter code doesn't run when inside a function


def display_rain():
    rain_image = Image.open("./images/rain_jpeg.jpg")
    rain_resized = rain_image.resize((250,250), Image.ANTIALIAS)
    rain_tk = ImageTk.PhotoImage(rain_resized)
    rain_label = tk.Label(root, image = rain_tk)
    rain_label.grid(row = 0, column = 0)
    rain_label.pack()

display_rain()

The code runs fine when outside of a function but doesn't appear to run at all when inside it. I've tried restarting Python and renaming the function.


Solution

  • Your image is being garbage collected. This works.

    import tkinter as tk
    from PIL import Image, ImageTk
    
    
    root = tk.Tk()
    root.geometry("800x600")
    
    #store all images in this dict so garbage collection will leave them alone
    #it doesn't have to be named "images"; it just has to be a dict
    images = dict()
    
    
    def display_rain(row=0, column=0):
        #create and store the image if it doesn't exist
        if 'rain_tk' not in images:
            #unless you are making mips of this image you should probably  
            #~make it the proper size and get rid of the resize part
            image = Image.open("./images/rain_jpeg.jpg").resize((250,250), Image.ANTIALIAS)
            #you can add a name to reference the image by
            #this makes it cleaner than accessing the dict directly
            images['rain_tk'] = ImageTk.PhotoImage(image, name='rain')
            
        #make and return the label, in case you want to grid_forget it or change the image
        label = tk.Label(root, image='rain') #instead of image=images['rain_tk']
        label.grid(row=row, column=column)
        return label
        
    #you can easily display this wherever you want by filling in the row and column arguments
    #as an example, this would be displayed at row1 column2
    rain_lbl = display_rain(1, 2)
          
    root.mainloop()