1

I have faced strange behaviour of tkinter.Canvas and Image in them in particular. Program was made for generating PDFs with desired data. During editing I load current PDF as image into canvas widget for preview. Image is generated by PyMuPDF. First launch is looking fine - PDF loaded and displayed. But when image must be updated, it become invisible. By chance, I found that if I raise exception for image container, image updating itself.

import tkinter
from tkinter import ttk
import fitz

PREVIEW_WIDTH = 606
PREVIEW_HEIGHT = 430

def read_pdf()->tkinter.PhotoImage:
# open created temporary pdf for preview
    pdf = fitz.open('customLabel.pdf')
    page = pdf.load_page(0)
    pix = page.get_pixmap()
    imgdata = pix.tobytes('ppm')  # extremely fast!
    pdf_img = tkinter.PhotoImage(data = imgdata)
    print('Current image:',pdf_img)
    pdf.close()    
    return pdf_img

def update_preview(event):
    img = read_pdf()
    preview.itemconfig(pdf_preview, image=img)
# If line below is disabled, preview will not be updated
    pdf_preview[0]=0

root = tkinter.Tk()
frame = tkinter.Frame(root)
frame.pack()

pdf_img=read_pdf()
#setup canvas for preview and place into right frame
preview = tkinter.Canvas(frame, bg='white', width=PREVIEW_WIDTH, height=PREVIEW_HEIGHT)
preview.pack()
pdf_preview = preview.create_image(10,10, anchor='nw', image = pdf_img)
preview.bind('<Double-ButtonPress-1>',update_preview)

root.mainloop()

I have simplify the code as much as possible for demonstration. Image updates on Double Click. Any suggestions and advices is very much appreciated

I already tested update() and update_idleprocess() methods for all of widgets. I did deletion and creation new image into canvas.

  • `pdf_preview[0]=0` will raise exception because `pdf_preview` is an integer. So the execution of the application stops at that line (you can verify that by adding `print("done")` after that line and you won't see "done" in the console) and the image is not garbage collected. If the line is removed, the image is garbage collected and so you cannot see the image. – acw1668 Jan 19 '23 at 09:09
  • Ok, I slightly changed update function: ```def update_preview(): img = read_pdf() preview.delete(all) preview.create_image(10,10,anchor='nw', image = img) preview.after(300,preview.update()) ``` Now it appeared as i wanted and after timer gone. How to handle this correctly? – Павел Третьяков Jan 19 '23 at 09:27
  • https://stackoverflow.com/questions/16424091/why-does-tkinter-image-not-show-up-if-created-in-a-function `preview.img = read_pdf()` – Сергей Кох Jan 19 '23 at 10:50
  • Right now when `img` goes out of scope after `update_preview` exits, the `PhotoImage` is deleted from memory and can't be displayed on the canvas. Try making `img` a global variable. – TheLizzard Jan 19 '23 at 12:31

0 Answers0