pythontkintercanvastkinter-photoimage

Stop tkinter from flashing when switching Canvas PhotoImages?


My tkinter user-interface involves two large Canvas widgets that are used to display photographs. The photographs update periodically, since they are being fed from live cameras. Problem: with some probability, the Canvas flashes white as it switches photographs. This makes for a very irritating display. I cannot include my whole program, as it is complex and includes external hardware, but here is the core update code. Please, can someone suggest an improvement to it to get rid of the flashing?

from PIL import Image,ImageTk

def previewUpdate(bytes, cameraID):
    # Update whichever view just got a new image
    view = canvasPicker[cameraID]
        # gets a View object, subclass of Canvas, below
    image = bytesToImage(bytes)
    view.display(image)


class View(tk.Canvas):
    def __init__(self, parent, width=1000, height=750, index=-1):
        super().__init__(parent, width=width, height=height)
        self.width = width
        self.height = height
        . . .

    def display(self, image):
        self.scale = min(self.width / image.width, self.height / image.height)
        image1 = image.resize((int(image.width * self.scale), int(image.height * self.scale)))
        self.photoImage = ImageTk.PhotoImage(image=image1)
        try:
            self.itemconfig(self.imageObject, image=self.photoImage)
        except Exception as e:
            print("display failure:  ", e)

Solution

  • Thank you, Lone Lunatic, for highlighting the problem. This line:

    self.photoImage = ImageTk.PhotoImage(image=image1)
    

    with some probability allows the prior PhotoImage to be garbage collected before the following line displays the new one, and that leaves a white interval. Quite simple… if you have your head around the weird inner workings of tkinter and PhotoImages. Here is the corrected, working code:

    def display(self, image):
        self.scale = min(self.width / image.width, self.height / image.height)
        image1 = image.resize((int(image.width * self.scale), int(image.height * self.scale)))
        image2 = ImageTk.PhotoImage(image=image1)
        try:
            self.itemconfig(self.imageObject, image=image2)
            self.photoImage = image2
        except Exception as e:
            print("display failure:  ", e)