user3770670
user3770670

Reputation: 1

How to insert an image into a tkinter sub frame

I am trying to develop a program which has a main frame (root) from which other frames are opened and closed via a menu. The main frame has an image inserted ok but as soon as I open another frame and try to insert a new image using:

    canvas = Canvas(date-time_window, width = 200, height = 200, bg = 'yellow') 
canvas.create_image(0, 0, image = moon_photo, anchor = NW)

I get an error pyimage2 doesnt exist, but if I remove the reference to the frame:

    canvas = Canvas(width = 200, height = 200, bg = 'yellow')

the image appears in the root frame ok, but of course not in the one I want it in.

Is it possible to display images in more than one frame at a time?

I have also noticed that I get the same error with the image displayed in the main frame if I close the main frame and then re-open it with out a total restart. Again I get pyimage2 does not exist plus the canvas in the root frame is blank.

I have read comments on how tkinter deals with garbage and suspect this could be related. I have also read a comment saying that an image should have a second reference attached to it but have not been able to see how to implement this action yet.

Can this be done within tkinter or do I need to look into using pillow instead?

Sample code, original far to long to include.

The code is called from a menu in the root window and is meant to display local date and time info. I was trying to get a picture of the present moon phase included as well:

def date_time():
    date_time_window = Tk()
    date_time_window.title('Date & Time')
    date_time_window.geometry('650x350')

    # Widgets

    present_date = today

    main_heading = Label(date_time_window, text = 'Date & Time')
    line1 = Canvas(date_time_window, width = 650, height = 3)
    line1.create_line(0,2 , 650,2, width = 1, fill = 'cyan')
    date_txt = Label(date_time_window,text = 'Date: ')
    date_value = Label(date_time_window, text =  today.strftime('%d') + '/' +       today.strftime('%m') + '/' + today.strftime('%y'))
    time_utc_txt = Label(date_time_window, text = 'UTC Time:')
    time_utc_value = Label(date_time_window, text = str(datetime.utcnow())[11:19])
    dls_txt = Label(date_time_window, text = 'DLS on/off: ')

    if moon_phase_number == 0:
        moon_photo = PhotoImage( file = 'images\moon_phase_0.gif')
    elif moon_phase_number == 1:
        moon_photo = PhotoImage( file = 'images\moon_phase_1.gif')


    canvas = Canvas(date_time_window, width = 200, height = 200, bg = 'yellow')        
    canvas.create_image(0, 0, image = moon_photo, anchor = NW)

    canvas.place( x = 300, y = 150)

    close_btn.configure( command = date_time_window.destroy)

    date_time_window.mainloop()

Upvotes: 0

Views: 3349

Answers (1)

Kevin
Kevin

Reputation: 76194

I can't debug the code sample given without a SSCCE, but I'll attempt to answer your remaining questions satisfactorily.


Is it possible to display images in more than one frame at a time?

Yes, there's no particular restriction on the number of frames which may contain images.


I have also read a comment saying that an image should have a second reference attached to it but have not been able to see how to implement this action yet.

That comment was probably in reference to this document:

Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.

To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:

label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()

Similarly, you should attach moon_photo to one of your widgets. canvas.image = moonphoto would be sufficient.


Can this be done within tkinter or do I need to look into using pillow instead?

People generally recommend PIL/Pillow for displaying images, because PhotoImage can only display gif and pgm images. PIL's ImageTk.PhotoImage class supports many more kinds of formats. However, since you're only trying to render gifs here, you don't need anything other than Tkinter.

Upvotes: 1

Related Questions