具有自动重影背景图像的Tkinter顶级窗口不起作用



我能够在tkinter中创建一个正常的窗口,该窗口具有与窗口本身一起调整大小的背景图像。但我不能为顶级窗口做同样的事情。从Toplevel派生的TopWin窗口在不执行任何操作的情况下无限期调整大小。我不明白为什么和什么是问题。我在下面报告了我的测试代码:

from tkinter import *
from PIL import Image, ImageTk
class FrameWin(Frame):
def __init__(self, master, *pargs):
Frame.__init__(self, master, *pargs)
self.image = Image.open("../idata/bkg-3.png")
self.img_copy= self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.pack(fill=BOTH, expand=YES)
self.background.bind('<Configure>', self._resize_image)
#---------------------------------------------------------------------------
def _resize_image(self,event):
new_width = event.width
new_height = event.height
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image = self.background_image)
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
class TopWin(Toplevel):
def __init__(self, master, **kwargs):
# super().__init__(**kwargs)
Toplevel.__init__(self, **kwargs)
self.image = Image.open("../idata/bkg-3.png")
self.img_copy= self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.pack(fill=BOTH, expand=YES)
self.background.bind('<Configure>', self._resize_image)
#---------------------------------------------------------------------------
def _resize_image(self,event):
new_width = event.width
new_height = event.height
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image = self.background_image)
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------

def workingMain():
root = Tk()
root.title("Title")
root.geometry("600x400")
root.configure(background="black")
w = FrameWin(root)
w.pack(fill=BOTH, expand=YES)
root.mainloop()
#---------------------------------------------------------------------------
def notWorkingMain():
root = Tk()
root.title("Title")
root.geometry("600x400")
root.configure(background="black")
w = TopWin(root)
root.mainloop()
#---------------------------------------------------------------------------
notWorkingMain()
#---------------------------------------------------------------------------
#---------------------------------------------------------------------------

FrameWin之所以有效,是因为在标签和框架上使用了fill = BOTHexpand = YES。我不确定为什么这会起作用,但我认为当调整窗口大小时,标签也会调整大小,这会触发Configure事件,并将图像调整为窗口的大小。如果不使用fillexpand,则图像将重复调整大小,直到填充窗口,这与调用Configure事件直到标签填充窗口时TopWin所面临的问题类似。一旦它填充了窗口,它就不能再展开了,所以Configure就不再被调用了。

要解决此问题,可以添加checktheresize方法来检查窗口和图像的大小是否相同。如果不是,则展开图像。这样可以防止图像无限扩展。请注意,事件绑定在TopLevel本身上,而不是在Label上。

class TopWin(Toplevel):
def __init__(self, master, **kwargs):
# super().__init__(**kwargs)
Toplevel.__init__(self, **kwargs)
self.image = Image.open("../idata/bkg-3.png")
self.img_copy= self.image.copy()
self.background_image = ImageTk.PhotoImage(self.image)
self.background = Label(self, image=self.background_image)
self.background.pack(fill=BOTH, expand=YES)
self.bind('<Configure>', self._resize_image) # Bind the toplevel, not the label
#---------------------------------------------------------------------------
def _resize_image(self,event):
# These are now the height/width of the window
new_width = event.width
new_height = event.height
# Check if the image is the same size as the window
if self.background.winfo_width() != new_width or self.background.winfo_height() != new_height:
# If it isn't, resize
self.image = self.img_copy.resize((new_width, new_height))
self.background_image = ImageTk.PhotoImage(self.image)
self.background.configure(image = self.background_image)

最新更新