【发布时间】:2018-07-09 15:21:56
【问题描述】:
我有一个程序,当我按下键盘上的热键时,它会在屏幕上显示图像。根据按下的键,将显示不同的图像。
在没有输入 3 秒后,我的根 Tk 得到 withdraw()n 所以屏幕上什么都没有。
现在,每当我想显示图像时,我都会调用此函数:
def drawOverlay(self, index):
self.canvas.itemconfig(self.overlayWidget, image=self.overlayImages[index])
self.deiconify()
问题是我看到旧图像几毫秒后才被替换。
我试图找出为什么会有延迟,尽管我 deiconify() 只是在我切换图像并遇到 this answer 建议使用根的 after() 调用 deiconify() 之后。我试过了,当它仍然不起作用时,我玩了一下这个电话,发现那个电话
self.after(1000, self.deiconify())
使旧图像恰好出现 1 秒钟,然后被新图像替换。
这让我相信Tk 或Canvas 在withdraw()n 时无法更新。有没有办法解决?我宁愿在图像显示之前有一个短暂的延迟,而不是旧图像在屏幕上闪烁几帧,但我不知道如何做到这一点。
编辑:所以我是个白痴,因为括号而实际上调用deiconify 而不是将其传递给after。
这确实可以修复在此期间出现的旧图像,但不能修复闪烁。
Edit2:我设法用下面的代码重现了这个问题。
按键盘上的任意键都会出现一个绿色矩形。等待它消失然后按另一个键将出现一个红色矩形。
只有有时您才能看到闪烁的情况,因此请多试几次。当-transparentcolor 未设置时,我无法重现,但我不知道这是由于选项是问题还是由于减少的渲染时间使问题几乎无法察觉。设置overrideredirect 后也更容易看到。
Edit3:我通过使用实际图像进一步简化了代码。即使没有按键或其他事件回调,此代码也会在显示图像之前产生黑色闪光。 -transparentcolor 和 overrideredirect(True) 似乎对于重现这一点至关重要。在此之前手动调用update() 会降低这种情况发生的频率,但仍会导致在较大图像上持续闪烁。这表明渲染时间是因素之一。
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.after(1000, self.deiconify())不会做你认为的那样。它立即调用deiconify,然后休眠一秒钟。 -
请提供minimal reproducible example,并让我们知道您在哪个平台上运行。
-
@BryanOakley 我刚刚注意到自己。不幸的是,这并不能解决整个问题。我为我的 Tk 类添加了源代码。我正在使用 Windows 8.1
-
请不要提供所有代码。创建一个minimal reproducible example。您发布的内容有太多不相关的代码。
-
请阅读minimal reproducible example 是什么。您的代码不完整,也不是最低限度的。例如,
resizable真的是问题的一部分吗?