I have a program that will show an image on screen when a hotkey is pressed on my keyboard. Depending on which key was pressed a different image will be shown.
After 3 seconds of no input my root Tk gets withdraw()
n so there is nothing on screen.
Now, whenever I want to show an image I call this function:
def drawOverlay(self, index):
self.canvas.itemconfig(self.overlayWidget, image=self.overlayImages[index])
self.deiconify()
The problem is that I see the old image for a few milliseconds before it is replaced.
I tried to find out why there is the delay eventhough I deiconify()
only after i switched the image and came across this answer which suggested to call deiconify()
using the root's after()
. I tried that and when it still didn't work I played around with the call and found out that calling
self.after(1000, self.deiconify())
causes the old image to appear for exactly 1 second after which it is replaced with the new one.
This leads me to believe that the Tk
or the Canvas
is unable to update while it is withdraw()
n. Is there any way around this? I'd rather have a short delay before the image is displayed than the old image flashing on the screen for a few frames but I have no idea how to accomplish this.
Edit: So I'm an idiot for actually calling deiconify
instead of just passing it to after
because of the parantheses.
That does fix the old image appearing for the duration but does not fix the flashing.
Edit2: I managed to reproduce this problem with the following code.
Pressing any key on the keyboard will make a green rectagle appear. Waiting for it to vanish and then pressing another key will make a red rectangle appear.
Only sometimes can you see the flashes happening so try for a couple times. I did not manage to reproduce when -transparentcolor
isnt set but I can't tell if this is due to the option being the problem or due to the reduced rendering times making the problem almost imperceptable. It is also a bit easier to see then overrideredirect
is set.
Edit3: I have worked the code down further by using actual images. Even without the keypress or additional event callbacks this code produces a black flash before displaing the image. -transparentcolor
and overrideredirect(True)
seem to be vital to reproducing this. Manually calling update()
before reduces the frequency of this ocurring but still causes flashing consistently on larger images. This points to rendering time being one of the factors.
from tkinter import Tk, Canvas
from PIL import ImageTk, Image
TRANSCOLOR = "blue"
IMAGE_SMALL = "overlay.png"
IMAGE_LARGE = "overlayRaw.png"
class Overlay(Tk):
def __init__(self):
Tk.__init__(self)
self.rawImage = Image.open(IMAGE_SMALL)
self.image = ImageTk.PhotoImage(self.rawImage)
self.canvas = Canvas(self, width = self.rawImage.size[0], height = self.rawImage.size[1])
self.canvas.pack()
self.wm_attributes('-transparentcolor', TRANSCOLOR) # If disabled stops the flashes from ocurring even on large images.
self.overrideredirect(True) # If disabled the Windows animation for opening windows plays. Stops the flashing from ocurring
self.withdraw()
self.overlayWidget = self.canvas.create_image(0, 0, image = self.image, anchor = "nw")
self.deiconify() # Flashes Clearly Everytime
## self.update_idletasks()
## self.deiconify() # Only Flashes Sometimes. Always flashes on large images
## self.update()
## self.deiconify() # Only Flashes Sometimes. Always flashes on large images
## self.after(0, self.deiconify) # Flashes Clearly everytime
## self.after(200, self.deiconify) # Only Flashes Sometimes. Always flashes on large images
## self.update()
## self.after(200, self.deiconify) # Flashes Clearly Everytime
o = Overlay()
o.mainloop()