如何在带背景图的tkinter窗口中叠加可随窗口自适应缩放的图片
解决方案
问题根因
- grid布局出现白色边框:
ResizeCls类初始化时父类调用参数错误,kwargs前缺少**,导致传入的bd=0等边框参数未生效,加上Frame默认带高亮边框和内边距,最终出现白边。 - 叠加图片无法同步缩放:原
resize方法取父容器宽高计算缩放尺寸,逻辑存在误差,且重叠的grid控件未配置sticky=NSEW,无法跟随单元格同步拉伸。 place_forget失效:大多是因为控件重绘事件逻辑冲突,或未正确持有控件引用导致被GC回收,优化后如果需要切换回place布局也可正常使用。
修改后的完整代码
import os import sys from tkinter import * from PIL import Image, ImageTk class ResizeCls(Frame): def __init__(self, master, index, *args, **kwargs): # 修正参数传递错误,补全**kwargs,同时默认关闭高亮边框 super().__init__(master, *args, highlightthickness=0, **kwargs) self.image = Image.open(index) self.image_copy = self.image.copy() self.background = ImageTk.PhotoImage(self.image) self.img = Label(self, image=self.background, bd=0, highlightthickness=0) self.img.pack(fill='both', expand=True) self.img.bind('<Configure>', self.resize) def resize(self, event): # 直接用事件返回的当前控件宽高,适配更准确 self.image2 = self.image_copy.resize((event.width, event.height)) self.background2 = ImageTk.PhotoImage(self.image2) self.img.config(image=self.background2) class TopCls(Frame): def __init__(self, master, folder, path_lst=None, *args, **kwargs): super().__init__(master, *args, **kwargs) self.folder = folder self.path_lst = [os.path.join(self.folder, name) for name in os.listdir(self.folder) if name.lower().endswith(('.png', '.jpg', '.gif'))] # 背景图:添加sticky=NSEW跟随单元格缩放 self.frame_image_delay_complete = ResizeCls(self, self.path_lst[0], bd=0) self.frame_image_delay_complete.grid(column=0, row=0, sticky=NSEW) # 叠加图:同单元格叠加,默认隐藏 self.frame_image_mobil_tutorial = ResizeCls(self, self.path_lst[1], bd=0) self.frame_image_mobil_tutorial.grid(column=0, row=0, sticky=NSEW) self.frame_image_mobil_tutorial.grid_remove() # 切换文本标签 self.lbl_text_guia = Label(self, text='Insert / hide image', font=('Calibri',7,'bold'), bg='black' , fg='white', bd=0) self.lbl_text_guia.place(x=2, y=48) self.lbl_text_guia.bind('<Button-1>', self.open_image_miniature) self.bind('<Configure>', self.new_position_text_guia) self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) def new_position_text_guia(self, event): toplevel_width = self.master.winfo_width() / 35 toplevel_height = self.master.winfo_height() / 13 x = int(toplevel_width) y = int(toplevel_height) self.lbl_text_guia.place(x=x, y=y) def open_image_miniature(self, event): if self.frame_image_mobil_tutorial.grid_info() == {}: self.frame_image_mobil_tutorial.grid() else: self.frame_image_mobil_tutorial.grid_remove() if __name__ == "__main__": if len(sys.argv) > 1: folder = sys.argv[1] else: folder = os.getcwd() root = Tk() root.geometry('300x300+300+300') frm = TopCls(root, folder) frm.pack(fill='both', expand=True) # 让TopCls跟随主窗口缩放 root.mainloop()
关键修改说明
- 修正了父类参数传递错误,所有图片控件默认关闭边框,彻底消除白边问题
- 缩放逻辑改用事件返回的控件实时尺寸,所有叠加图层都能同步适配窗口大小
- 给grid布局的图片控件新增
sticky=NSEW配置,确保控件跟随单元格同步拉伸 - 主窗口下的
TopCls新增fill='both', expand=True配置,确保根容器跟随窗口缩放
如果需要切换为place布局实现叠加,只需要把grid相关逻辑替换为place,调用place_forget()即可正常隐藏控件,不会再出现失效问题。
内容的提问来源于stack exchange,提问作者Eliizahh
相关产品推荐
相关产品推荐

