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