Tkinter执行Canvas保存函数前Frame控件无法销毁问题求解
问题原因
Tkinter的界面更新由内部事件循环驱动,你调用save_canvas_frame.destroy()时,销毁指令只会被加入事件队列,不会立刻完成界面重绘。后续的截图操作会在事件循环处理销毁指令前执行,因此截图中还是会保留Frame的内容。
解决方法
在销毁Frame后、截图前,调用root.update()或root.update_idletasks()强制刷新界面,等待所有待处理的UI事件执行完成后再进行截图即可,后者只会处理UI重绘类的空闲事件,不会触发其他用户输入事件,安全性更高。
修改后的代码
from tkinter import * from PIL import ImageGrab root = Tk() canvas = Canvas(root,width=root.winfo_screenwidth(),height=root.winfo_screenheight(), bg="white",highlightthickness=0,cursor='dot') canvas.pack(side=RIGHT,fill=Y) save_canvas_frame = Frame(root,width=84,height=root.winfo_screenheight(),bg="#EFEFEF") save_canvas_frame.place(x=0,y=0) def save(): # 销毁侧边栏Frame save_canvas_frame.destroy() # 强制刷新界面,等待销毁操作生效 root.update_idletasks() # 执行截图保存逻辑 x=root.winfo_rootx()+canvas.winfo_x() y=root.winfo_rooty()+canvas.winfo_y() x1=x+canvas.winfo_width() y1=y+canvas.winfo_height() pic = ImageGrab.grab((x, y, x1, y1)) pic.save("pic.png") save_button = Button(save_canvas_frame,text="Save Canvas",command=save) save_button.place(x=0,y=0) root.mainloop()
如果你不想用强制刷新的方式,也可以把截图逻辑用
after方法延后执行,给事件循环留足够的时间处理销毁事件:def save(): save_canvas_frame.destroy() # 延后10ms执行截图逻辑 root.after(10, grab_canvas) def grab_canvas(): x=root.winfo_rootx()+canvas.winfo_x() y=root.winfo_rooty()+canvas.winfo_y() x1=x+canvas.winfo_width() y1=y+canvas.winfo_height() pic = ImageGrab.grab((x, y, x1, y1)) pic.save("pic.png")
内容的提问来源于stack exchange,提问作者Ori
相关产品推荐
相关产品推荐

