tkinter创建子组件后,导致父组件的关闭事件被触发时,连续执行了两次事件函数
本帖最后由 SendingSonGY 于 2024-9-9 13:09 编辑就不附图了,我写了伪代码。敬请各位大佬帮帮:dizzy:小弟,问了ai,ai也不懂:'(weeqw,大佬们快来呀。 本帖最后由 冰茶荼 于 2024-9-9 14:27 编辑
不懂py 但是从代码来看 label 组件也触发了销毁事件 看看是否可以在销毁事件中判断来源
https://s21.ax1x.com/2024/09/09/pAmC1gI.png
https://s21.ax1x.com/2024/09/09/pAmPGW9.png
https://s21.ax1x.com/2024/09/09/pAmPJzR.png
经过尝试 给出以下2个解决方案:
方案1:
import threading
import time
import tkinter
win = tkinter.Tk()
win.width = 200
win.height = 200
def a():
top = tkinter.Toplevel(win)
top.pack_slaves()
def x():
# 这是子组件,不添加这个子组件时,关闭top窗口只print一次。但是添加时,就会print两次。不pack也会。不使用子线程也会。目前排除线程问题。
la = tkinter.Label(top,text='出现')
la.pack()
def b():
# 使用 top.unbind 来取消剩余事件的触发(触发事件的event不一定是top 是最后一个被添加的组件)
top.unbind('<Destroy>')
top.bind('<Destroy>',b)
t = threading.Thread(target=x)
t.start()
btn = tkinter.Button(win,text='点我',command=a)
btn.pack()
win.mainloop()
方案2:
import threading
import time
import tkinter
win = tkinter.Tk()
win.width = 200
win.height = 200
def a():
top = tkinter.Toplevel(win)
top.pack_slaves()
def x():
# 这是子组件,不添加这个子组件时,关闭top窗口只print一次。但是添加时,就会print两次。不pack也会。不使用子线程也会。目前排除线程问题。
la = tkinter.Label(top,text='出现')
la.pack()
def b():
top.destroy()
# 使用窗口关闭协议通信
top.protocol("WM_DELETE_WINDOW", b)
t = threading.Thread(target=x)
t.start()
btn = tkinter.Button(win,text='点我',command=a)
btn.pack()
win.mainloop()
搞个网盘吧 下载附件还得掏钱 冰茶荼 发表于 2024-9-9 13:31
搞个网盘吧 下载附件还得掏钱
啊?这个还要钱啊{:1_907:} 我下载了代码,然后直接运行。打开主窗口,又打开子窗口,关闭子窗口,print一次,关闭主窗口没有print。我又运行程序,打开主窗口,然后直接关闭主窗口,没有print,直接退出了。我没有测试到楼主所说的问题。可能python版本不一样。我贴出我运行的截图。
Clarkchaoren 发表于 2024-9-9 13:43
我下载了代码,然后直接运行。打开主窗口,又打开子窗口,关闭子窗口,print一次,关闭主窗口没有print。我 ...
代码您看没,我是把子组件的创建注释掉了的 冰茶荼 发表于 2024-9-9 14:01
不懂py 但是从代码来看 label 组件也触发了销毁事件 看看是否可以在销毁事件中判断来源
谢谢大佬,确实是这样,您真帅。看了您的阐释以及给出的方案,我很高兴,不仅仅是因为我的问题得到了解决,更是我学到了一些新知识点,比如event.widget,我从来没试过event下的属性和方法,这个属性在此处的调试真的一眼就点醒我了。但是我还是不太理解为什么父组件绑定的destory事件函数会被子组件的destory触发 SendingSonGY 发表于 2024-9-9 15:01
谢谢大佬,确实是这样,您真帅。看了您的阐释以及给出的方案,我很高兴,不仅仅是因为我的问题得到了解决 ...
因为你创建子组件的时候 target填写的是top,你又监听了top下的销毁,当top窗口被销毁的时候,下面的所有子组件都会触发销毁回调,我的理解是这样的 冰茶荼 发表于 2024-9-9 15:08
因为你创建子组件的时候 target填写的是top,你又监听了top下的销毁,当top窗口被销毁的时候,下面的所有 ...
import threading
import time
import tkinter
win = tkinter.Tk()
win.width = 200
win.height = 200
def a():
top = tkinter.Toplevel(win)
top.pack_slaves()
def x():
la = tkinter.Label(top,text='出现了')
la.pack()
def b(e):
if e.widget == top:
for w in win.children.values():
w.pack_forget()
top.bind('<Destroy>',b)
t = threading.Thread(target=x)
t.start()
btn = tkinter.Button(win,text='点我',command=a)
btn.pack()
win.mainloop()
大佬您再帮我看看这个错误呗,我在destory事件函数中写了隐藏所有win的子组件,但是top窗口也被算在内了,此时top窗口难道不是已经被销毁了吗?
SendingSonGY 发表于 2024-9-9 15:34
import threading
import time
b触发的时候top窗口应该还没有销毁
页:
[1]