Python 3.x Tkinter按钮状态修改失败问题求助
问题分析
报错_tkinter.TclError: invalid command name ".!button"的核心原因是:你在modify函数里先调用errorbox.destroy()销毁了主窗口,之后又尝试修改属于这个窗口的按钮(mods/dell/close)的状态——窗口销毁后,它的所有子控件也会被销毁,此时再操作这些控件就会触发无效命令的错误。
另外代码还有两处逻辑问题:
modify里的while True循环完全多余,直接去掉即可delete函数存在缩进错误(deldel函数缩进不正确),且弹出确认对话框后立刻恢复按钮状态,导致按钮还没等对话框关闭就变回可用,违背了“操作期间禁用按钮”的需求
修复方案
1. 修复modify函数逻辑
如果需要保留原窗口(errorbox),打开新窗口时禁用原按钮,等新窗口关闭后再恢复状态,修改如下:
def modify(): # 先禁用按钮 mods.config(state=DISABLED) dell.config(state=DISABLED) close.config(state=DISABLED) # 用Toplevel创建新窗口(不要销毁原窗口) win = Replacy(self, dbn, self.coln, self.it, client, tree, item) win.resizable(False, False) win.grab_set() # 等待新窗口关闭后再执行后续代码 errorbox.wait_window(win) # 新窗口关闭后恢复按钮状态 mods.config(state=NORMAL) dell.config(state=NORMAL) close.config(state=NORMAL)
如果必须销毁原窗口(errorbox),直接去掉恢复按钮状态的代码即可(原窗口销毁后按钮已不存在):
def modify(): mods.config(state=DISABLED) dell.config(state=DISABLED) close.config(state=DISABLED) # 销毁原窗口 errorbox.destroy() win = Replacy(self, dbn, self.coln, self.it, client, tree, item) win.resizable(False, False) win.grab_set()
2. 修复delete函数逻辑
修正缩进错误,调整按钮状态恢复时机,等确认对话框关闭后再恢复:
def delete(): # 先禁用按钮 mods.config(state=DISABLED) dell.config(state=DISABLED) close.config(state=DISABLED) def deldel(): tree.delete(item) eeeeerrorbox.destroy() coln.delete_one(self.it) errorbox.destroy() eeeeerrorbox = Tk() eeeeerrorbox.geometry("255x80") eeeeerrorbox.title("Error") eeeeerrorbox.iconbitmap(False, fold +"/info.ico") l2=Label(eeeeerrorbox, text='Are you sure you want to delete this entry?') l2.grid(row=0, column=0, columnspan=3, pady=(7, 10), padx=10, sticky="w") dellll = ttk.Button(eeeeerrorbox, text="Yes", command=deldel, width=7) dellll.grid(row=1, column=0, columnspan=2) closeee = ttk.Button(eeeeerrorbox, text="No", command=eeeeerrorbox.destroy, width=7) closeee.grid(row=1, column=2) eeeeerrorbox.resizable(False, False) # 等待确认对话框关闭后再恢复按钮状态 errorbox.wait_window(eeeeerrorbox) mods.config(state=NORMAL) dell.config(state=NORMAL) close.config(state=NORMAL)
额外提示
- Tkinter中尽量避免多次创建
Tk()实例,新窗口建议用Toplevel(),共享同一个主事件循环,避免多窗口事件循环冲突 grab_set()可让新窗口成为模态窗口,阻止用户操作原窗口,配合wait_window()能准确获取窗口关闭时机
内容的提问来源于stack exchange,提问作者Savvidaios
相关产品推荐
相关产品推荐

