在CustomTkinter中创建多界面时遭遇invalid command name错误求助
问题描述
使用CustomTkinter创建多界面切换时,出现以下报错导致程序卡住,该问题在普通Tkinter中未出现:
invalid command name "1775568714624update"
while executing
"1775568714624update"
("after" script)
invalid command name "1775530397696check_dpi_scaling"
while executing
"1775530397696check_dpi_scaling"
("after" script)
invalid command name "1775587007232_click_animation"
while executing
"1775587007232_click_animation"
("after" script)
原问题代码
from customtkinter import (CTk, CTkButton) def fun(): root.destroy() inp = CTk() inp.mainloop() root = CTk() root.geometry('250x250') but = CTkButton(master=root, width=50, height=25,text="TEST" ,command=fun).pack(expand=True) root.mainloop()
报错原因
CustomTkinter的组件(如CTkButton)会在后台启动多个after定时任务,用于处理点击动画、DPI缩放检查、界面更新等逻辑。当直接调用root.destroy()销毁主窗口时,这些后台任务并未被终止,仍然会尝试调用已被销毁的组件关联的命令,从而触发"invalid command name"错误。普通Tkinter的组件没有这些额外的后台任务,因此不会出现该问题。
解决方案
方案1:使用CTkToplevel创建新窗口(推荐)
CustomTkinter官方推荐只保留一个主CTk实例,其他窗口使用CTkToplevel,这样可以避免多主窗口的资源管理问题:
from customtkinter import (CTk, CTkButton, CTkToplevel) def fun(): # 创建顶级窗口,关联主root inp = CTkToplevel(root) inp.geometry('250x250') inp.title("新窗口") # 可选:设置新窗口为模态,禁止操作原窗口 inp.grab_set() root = CTk() root.geometry('250x250') CTkButton(master=root, width=50, height=25, text="TEST", command=fun).pack(expand=True) root.mainloop()
方案2:正确终止主窗口的后台任务后再销毁
如果必须销毁主窗口并创建新的CTk实例,需要先取消所有after任务,再销毁窗口:
from customtkinter import (CTk, CTkButton) def fun(): # 取消主窗口所有未执行的after任务 root.after_cancel("all") root.destroy() # 创建新的主窗口 inp = CTk() inp.geometry('250x250') inp.mainloop() root = CTk() root.geometry('250x250') CTkButton(master=root, width=50, height=25, text="TEST", command=fun).pack(expand=True) root.mainloop()
内容的提问来源于stack exchange,提问作者عبدالرحمن سعد

