3
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.

  • add `global root` to the first line of the function, and see what happens. Also, pick either `pack` or `grid`, not both. Also, store the image in a global dictionary with any other images you want to load. The way you are doing it, your image is a prime candidate for garbage collection. – OneMadGypsy Aug 22 '20 at 17:13
  • Could you please be more specific? What exactly happens when it work (eg what do you expect it to do) and what happens when it doesn't? Are there any error messages? – jthulhu Aug 22 '20 at 17:15
  • @MichaelGuidry That will not make any difference –  Aug 22 '20 at 17:15
  • @AryanParekh - my edit about garbage collection probably will though. – OneMadGypsy Aug 22 '20 at 17:19
  • @MichaelGuidry I'm not sure because there is a reference to that label within root, I think, so the garbage collector should not remove it.... – jthulhu Aug 22 '20 at 17:22

1 Answers1

3

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() 
OneMadGypsy
  • 4,640
  • 3
  • 10
  • 26
  • 1
    Legend, that works perfectly and I never knew that you could pass positions as parameters to the function. Why did you put a `*` before `Images`, is that just convention? – Benjamin McDowell Aug 22 '20 at 18:00
  • Using `[*SomeDict]` is equivalent to `SomeDict.keys()` – OneMadGypsy Aug 22 '20 at 18:03
  • Acutally, this is useless as dicts already check containment within keys, which means ```a in some_dict.keys() == a in some_dict``` – jthulhu Aug 22 '20 at 18:04
  • @BlackBeans ~ lol, I always forget if its `key in dict:` or `value in dict` so, I just get specific. Maybe your comment will stick in my head as a reminder. – OneMadGypsy Aug 22 '20 at 18:06
  • Hello again, now the image doesn't appear when inside a function but again, works perfectly fine when outside a function. `weather_main = 'Clouds'` `if weather_main + '_tk' not in [*Images]:` `wow = tk.Label(root, text = 'its a match')` `wow.pack()` `image_1 = ImageTk.PhotoImage(Image.open("./images/" + weather_main + ".jpg"))` `Images["main_type"] = weather_main` `finale = tk.Label(root, image=image_1)` `finale.pack()` `wow = tk.Label(root, text = 'its a match')` `wow.pack()` – Benjamin McDowell Aug 25 '20 at 11:08
  • @BenjaminMcDowell you are saving the word "Clouds" in `Images`. Do: `Images['main_type'] = image_1` and `image=Images['main_type']` – OneMadGypsy Aug 25 '20 at 14:14