如何正确关闭内嵌matplotlib的tkinter Toplevel窗口?
问题修复方案
问题根源
程序无法正常退出是三个原因共同导致的:
- 多余的事件循环:打开Toplevel弹窗时额外调用了
popupgraph1.mainloop(),整个Tk程序只需要根窗口的1个mainloop()即可,多余的事件循环在弹窗关闭后仍会残留,阻塞进程退出。 - Matplotlib资源未释放:
plt.subplots()创建的画布对象没有在弹窗关闭时主动销毁,matplotlib的后台引用会阻止进程结束。 - 无弹窗关闭清理逻辑:Toplevel窗口关闭事件没有绑定对应的资源清理回调。
修复步骤
- 移除
open_graph方法中弹窗的mainloop()调用,让弹窗共用根窗口的事件循环 - 给
PopUP_Graph绑定窗口关闭事件,关闭时主动释放matplotlib画布资源,再销毁弹窗对象
完整修复代码
import tkinter as tk from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import matplotlib.pyplot as plt class PopUP_Graph(tk.Toplevel): def __init__(self, *args, **kargs): super().__init__(*args, **kargs) self.fig, self.ax = plt.subplots() self.drawing_area = FigureCanvasTkAgg(self.fig, master=self) self.drawing_area.draw() self.toolbar = NavigationToolbar2Tk(self.drawing_area, self) self.toolbar.update() self.drawing_area.get_tk_widget().pack(side="top", fill="both", expand=1) # 绑定窗口关闭事件 self.protocol("WM_DELETE_WINDOW", self._on_close) def _on_close(self): # 释放matplotlib画布资源 plt.close(self.fig) # 销毁弹窗 self.destroy() class App: def __init__(self, root): self.master = root self.button = tk.Button(root, text="Open graph", command=self.open_graph) self.button.grid(column=0, row=0) def open_graph(self): popupgraph1 = PopUP_Graph(self.master) # 移除多余的mainloop调用 w, h = 900, 600 root = tk.Tk() root.geometry(f'{w}x{h}+0+0') app = App(root) root.mainloop()
修改说明
- 新增的
_on_close方法会在用户点击弹窗关闭按钮时触发,先清理matplotlib占用的资源,再安全销毁弹窗对象 - 移除多余的事件循环后,整个程序只有根窗口的一个事件循环调度所有UI交互,关闭根窗口时所有子组件会同步销毁,不会出现残留进程的问题
内容的提问来源于stack exchange,提问作者Daniel Casasampera
相关产品推荐
相关产品推荐

