关闭含Matplotlib图形的CustomTkinter窗口后报错的解决方案咨询
CustomTkinter集成Matplotlib关闭窗口报错及程序残留问题解决
问题现象
关闭窗口后控制台输出以下错误,程序进程仍在后台持续运行:
invalid command name "2444841565824check_dpi_scaling" while executing "2444841565824check_dpi_scaling" ("after" script) invalid command name "2444841677504update" while executing "2444841677504update" ("after" script)
用户提供的示例代码:
from tkinter import * from customtkinter import * import matplotlib import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg matplotlib.use('TkAgg') plt.rcParams["figure.facecolor"] = "2b2b2b" plt.rcParams["axes.facecolor"] = "2b2b2b" plt.rcParams['font.family'] = 'serif' plt.rcParams['font.serif'] = ['Times New Roman'] + plt.rcParams['font.serif'] plt.rcParams['mathtext.default'] = 'regular' root = CTk() root.geometry('1000x600+200+40') root.minsize(width=800, height=600) root.title('Something') root.state("zoomed") EquationFrame = CTkFrame(root, height=800,width=500) EquationFrame.place(relx=0.239 , rely=0.03 , relwidth=0.4*1.8 , relheight=(0.3999*3)- 0.2688) EquationOutput = Label(EquationFrame) EquationOutput.place(relx=0.024, rely=0.3004,) figure = plt.figure(figsize=(13.25, 2)) ax = figure.add_subplot(111) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) canvas = FigureCanvasTkAgg(figure, master=EquationOutput) canvas.get_tk_widget().pack(side="top", fill="both", expand=True) canvas._tkcanvas.pack(fill="both", expand=True, side="top") ax.spines["right"].set_visible(False) ax.spines["left"].set_visible(False) ax.spines["top"].set_visible(False) ax.spines["bottom"].set_visible(False) ax.clear() ax.text(-0.15, 0.37, f"$(something)^2 * (something)^3$", fontsize=50, fontdict=None).set_color("white") root.mainloop()
解决方法
错误根源是Matplotlib的FigureCanvasTkAgg组件在窗口关闭时未被正确销毁,导致Tkinter的after定时任务仍尝试调用已释放的组件资源。以下是具体修复步骤:
1. 绑定窗口关闭事件,手动清理资源
给主窗口添加关闭回调函数,在窗口关闭前销毁Matplotlib的Canvas组件,释放相关资源:
def on_closing(): canvas.get_tk_widget().destroy() canvas._tkcanvas.destroy() plt.close(figure) # 若使用plt创建的figure,用此方法关闭;若用Figure类实例,改用figure.close() root.destroy() root.protocol("WM_DELETE_WINDOW", on_closing)
2. 替换原生Tkinter组件为CustomTkinter适配组件
原代码中使用的Label是Tkinter原生组件,换成CTkLabel能更好适配CustomTkinter的环境,避免潜在兼容问题:
EquationOutput = CTkLabel(EquationFrame, text="") EquationOutput.place(relx=0.024, rely=0.3004)
3. 优化Matplotlib实例创建方式
尽量避免使用plt.figure创建全局状态的figure,改用matplotlib.figure.Figure直接创建实例,减少全局资源干扰:
from matplotlib.figure import Figure figure = Figure(figsize=(13.25, 2))
完整修复后的代码
from customtkinter import * import matplotlib from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg matplotlib.use('TkAgg') # 配置Matplotlib样式 matplotlib.rcParams["figure.facecolor"] = "2b2b2b" matplotlib.rcParams["axes.facecolor"] = "2b2b2b" matplotlib.rcParams['font.family'] = 'serif' matplotlib.rcParams['font.serif'] = ['Times New Roman'] + matplotlib.rcParams['font.serif'] matplotlib.rcParams['mathtext.default'] = 'regular' def on_closing(): # 销毁Matplotlib相关组件 canvas.get_tk_widget().destroy() canvas._tkcanvas.destroy() figure.close() root.destroy() root = CTk() root.geometry('1000x600+200+40') root.minsize(width=800, height=600) root.title('Something') root.state("zoomed") root.protocol("WM_DELETE_WINDOW", on_closing) EquationFrame = CTkFrame(root, height=800, width=500) EquationFrame.place(relx=0.239, rely=0.03, relwidth=0.4*1.8, relheight=(0.3999*3)-0.2688) EquationOutput = CTkLabel(EquationFrame, text="") EquationOutput.place(relx=0.024, rely=0.3004) figure = Figure(figsize=(13.25, 2)) ax = figure.add_subplot(111) ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) # 隐藏所有坐标轴边框 for spine in ax.spines.values(): spine.set_visible(False) canvas = FigureCanvasTkAgg(figure, master=EquationOutput) canvas.get_tk_widget().pack(side="top", fill="both", expand=True) canvas._tkcanvas.pack(fill="both", expand=True, side="top") # 添加公式文本 ax.clear() ax.text(-0.15, 0.37, "$(something)^2 * (something)^3$", fontsize=50, color="white") root.mainloop()
关于auto-py-to-exe打包的影响
未修复前,打包后的程序关闭窗口后会残留进程,导致系统资源占用,甚至弹出错误提示;修复后,程序能正常关闭,不会出现残留问题,打包后的运行体验与本地调试一致。
内容的提问来源于stack exchange,提问作者Mr. Hussain AL Hussaini
相关产品推荐
相关产品推荐

