我有一个程序,当在键盘上按热键时,该程序会在屏幕上显示图像。根据所按下的键,将显示不同的图像。
3秒钟无输入后,我的根Tk得到withdraw()
n,因此屏幕上没有任何内容。
现在,每当我要显示图像时,我都会调用此函数:
def drawOverlay(self, index):
self.canvas.itemconfig(self.overlayWidget, image=self.overlayImages[index])
self.deiconify()
问题是在替换旧图像之前,我看到了几毫秒。
我试图找出为什么即使我切换图像并遇到this answer后,即使我使用
deiconify()
时也会出现延迟,建议使用根的deiconify()
调用after()
。我尝试了一下,当它仍然不起作用时,我打了个电话,发现那通电话self.after(1000, self.deiconify())
导致旧图片显示恰好1秒钟,之后将其替换为新图片。
这使我相信
Tk
n时Canvas
或withdraw()
无法更新。有没有办法解决?我宁愿在显示图像之前有一个短暂的延迟,而不是将旧图像在屏幕上闪烁几帧,但是我不知道如何实现此目的。编辑:因此,我是一个白痴,实际上是因为调用了
deiconify
而不是仅仅将其传递给after
。这确实可以修复在此期间出现的旧图像,但不能解决闪烁的问题。
Edit2 :我设法通过以下代码重现此问题。
按键盘上的任意键将显示绿色的重新标记。等待它消失,然后按另一个键将显示一个红色矩形。
仅在某些时候您可以看到闪烁的情况,因此请尝试几次。当未设置
-transparentcolor
时,我没有设法重现,但是我无法确定这是由于选项问题还是由于减少了渲染时间而使问题几乎无法察觉。设置overrideredirect
也会更容易看到。Edit3 :我已经通过使用实际图像进一步简化了代码。即使没有按键或其他事件回调,此代码在替换图像之前也会产生黑色闪烁。
-transparentcolor
和overrideredirect(True)
似乎对于重现这一点至关重要。在此之前手动调用update()
可以降低这种情况的发生频率,但仍会导致较大图像上的闪烁持续发生。这表明渲染时间是因素之一。overlay.png
overlayRaw.png
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()
最佳答案
我看不出会引起闪烁的现象。我的建议是在调用self.update
之前添加一个对deiconify
的显式调用。这应该指示tkinter重画 Canvas 上的所有内容。但是,如果您的平台上的tkinter推迟绘图直到映射了窗口,这将无济于事。
尝试替换此:
self.after(0,self.deiconify)
self.after(2000, self.hideOverlay)
有了这个:
self.update()
self.deiconify()