打开Toplevel时WM_DELETE_WINDOW提前执行重置计数器如何解决
问题根因
你遇到的逻辑异常是由以下几个明确的代码错误导致的:
- 最核心的错误:给
WM_DELETE_WINDOW协议绑定回调函数时,你写的是add_close(),加括号会当场执行该函数,而不是把函数本身作为回调传给协议绑定,这就是你每次点按钮计数器立刻被重置的直接原因。 - 冗余的
Toplevel.mainloop()调用:整个tkinter程序只需要主窗口运行一次mainloop()即可,给子窗口额外加mainloop()会导致事件循环逻辑异常。 - 计数器执行顺序错误:按钮点击后先执行
add_open()修改计数器,再执行addBook()判断是否可以开窗口,就算判断不通过计数器也会被异常修改,后续永远无法打开子窗口。 - 计数器写入逻辑错误:
add_open()用追加模式写1,多次点击后文件内会存在多个1,add_check()的判等逻辑会直接失效。
修复方案
1. 调整主窗口按钮逻辑
删除按钮command里的add_open()调用,把计数器修改逻辑移到addBook()内部,确保只有判断可以开窗口的时候才修改计数器:
btn1 = Button(root,text="Add Book",command=addBook).pack()
2. 修复addBook()函数
修改协议绑定的写法,删除冗余的子窗口mainloop:
def addBook(): if add_check(): # 先判断能不能开窗口 add_open() # 能开再修改计数器 AddBookWindow = Toplevel() # 原有窗口配置代码 AddBookWindow.protocol("WM_DELETE_WINDOW", add_close) # 只传函数名,不加括号
3. 修复计数器写入逻辑
把add_open()的追加模式改成覆盖写,避免文件内出现多个1:
def add_open(): with open(r"counters\addbook.txt", "w") as file: file.write("1")
4. 补充关闭窗口的销毁逻辑
原有add_close()只重置计数器,没有销毁子窗口,需要修改add_close(),先销毁窗口再重置计数器。如果子窗口对象作用域无法直接访问,可以用lambda传参绑定:
# 协议绑定处修改为 AddBookWindow.protocol("WM_DELETE_WINDOW", lambda: add_close(AddBookWindow)) # add_close修改为 def add_close(window): window.destroy() print("add close") with open(r"counters\addbook.txt", "w") as file: file.write("")
内容的提问来源于stack exchange,提问作者MG-LSJ
相关产品推荐
相关产品推荐

