Search code examples
pythonimagetkinterwindow

How can I close an image in a tkinter window without closing the window?


I am writing an application that consists of three tkinter windows on the same page: a calendar, a notepad and a 'picture of the day' which is fetched from a bank of images when initiated by the user. The image is named after the calendar date + .jpg. It works fine...the first time. When I select another date and retrieve the image for that date, it comes up behind the first image in the 'picture of the day' window. The problem is that the first image does not disappear when replaced by another. I do not want to close the window, just close the current picture and replace it by the new one. There might a simple way, but I spent hours searching for it. The code below of part of the application. Hopefully, it shows where the problem is. Can you point me in the right direction? Thanks

from tkinter import *
from PIL import ImageTk, Image
from tkinter import filedialog
import os

photo = Toplevel()
photo.geometry("300x250+1300+150")
photo.resizable(width=True, height=True)
photo.attributes("-topmost", True)

def openfn():  # To go fetch a new image
    filename = filedialog.askopenfilename(title='open')
    return filename
    root.destroy()
def open_img():  # To open a new image
    x = openfn()
    img = Image.open(x)
    img = img.resize((225,200), Image.ANTIALIAS)
    im = ImageTk.PhotoImage(img)
    panel = Label(photo, image=im)
    panel.image = im
    panel.pack()
    img=img.save(cal.calphoto) #  Saves the image (calphoto is date + .jpg)

def retrieve_photo(): #  To open an existing image 
    img=Image.open(cal.calphoto)
    im = ImageTk.PhotoImage(img)
    panel = Label(photo, image=im)
    panel.image = im
    panel.pack()

Solution

  • I changed a few things in your code. The main thing is the take the label with the image into the global scope so the function open_img() can make changes to it instead of creating a new label each time it is called. Below open_img() now configures the label to show the image selected each time it is called. (This is basically illustrating what Delrius said.)

    from tkinter import *
    from PIL import ImageTk, Image
    from tkinter import filedialog
    import os
    
    photo = Toplevel()
    photo.geometry("300x250+1300+150")
    photo.resizable(width=True, height=True)
    photo.attributes("-topmost", True)
    
    panel = Label(photo) # panel Label moved into global scope so the
    # functions below can access it
    
    def openfn():  
        filename = filedialog.askopenfilename(title='open')
        return filename
        root.destroy()
    def open_img():  
        x = openfn()
        img = Image.open(x)
        img = img.resize((225,200), Image.ANTIALIAS)
        im = ImageTk.PhotoImage(img)
        panel.config(image=im) # panel label is configured to show image selected
        panel.image = im
        panel.pack()