吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 556|回复: 9
收起左侧

[讨论] tkinter创建子组件后,导致父组件的关闭事件被触发时,连续执行了两次事件函数

[复制链接]
SendingSonGY 发表于 2024-9-9 12:57
本帖最后由 SendingSonGY 于 2024-9-9 13:09 编辑

就不附图了,我写了伪代码。敬请各位大佬帮帮小弟,问了ai,ai也不懂,大佬们快来呀。

draft.txt

697 Bytes, 下载次数: 4, 下载积分: 吾爱币 -1 CB

代码,注释都写在里面了

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

冰茶荼 发表于 2024-9-9 14:01
本帖最后由 冰茶荼 于 2024-9-9 14:27 编辑

不懂py 但是从代码来看 label 组件也触发了销毁事件 看看是否可以在销毁事件中判断来源









经过尝试 给出以下2个解决方案:
方案1:

[Python] 纯文本查看 复制代码
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:
[Python] 纯文本查看 复制代码
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
 楼主| SendingSonGY 发表于 2024-9-9 13:40
Clarkchaoren 发表于 2024-9-9 13:43
我下载了代码,然后直接运行。打开主窗口,又打开子窗口,关闭子窗口,print一次,关闭主窗口没有print。我又运行程序,打开主窗口,然后直接关闭主窗口,没有print,直接退出了。我没有测试到楼主所说的问题。可能python版本不一样。我贴出我运行的截图。 2.png
3.png
 楼主| SendingSonGY 发表于 2024-9-9 13:47
Clarkchaoren 发表于 2024-9-9 13:43
我下载了代码,然后直接运行。打开主窗口,又打开子窗口,关闭子窗口,print一次,关闭主窗口没有print。我 ...

代码您看没,我是把子组件的创建注释掉了的
 楼主| SendingSonGY 发表于 2024-9-9 15:01
冰茶荼 发表于 2024-9-9 14:01
不懂py 但是从代码来看 label 组件也触发了销毁事件 看看是否可以在销毁事件中判断来源

谢谢大佬,确实是这样,您真帅。看了您的阐释以及给出的方案,我很高兴,不仅仅是因为我的问题得到了解决,更是我学到了一些新知识点,比如event.widget,我从来没试过event下的属性和方法,这个属性在此处的调试真的一眼就点醒我了。但是我还是不太理解为什么父组件绑定的destory事件函数会被子组件的destory触发
冰茶荼 发表于 2024-9-9 15:08
SendingSonGY 发表于 2024-9-9 15:01
谢谢大佬,确实是这样,您真帅。看了您的阐释以及给出的方案,我很高兴,不仅仅是因为我的问题得到了解决 ...

因为你创建子组件的时候 target填写的是top,你又监听了top下的销毁,当top窗口被销毁的时候,下面的所有子组件都会触发销毁回调,我的理解是这样的
 楼主| SendingSonGY 发表于 2024-9-9 15:34
冰茶荼 发表于 2024-9-9 15:08
因为你创建子组件的时候 target填写的是top,你又监听了top下的销毁,当top窗口被销毁的时候,下面的所有 ...

[Python] 纯文本查看 复制代码
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窗口难道不是已经被销毁了吗?
冰茶荼 发表于 2024-9-9 15:51
SendingSonGY 发表于 2024-9-9 15:34
[mw_shl_code=python,true]import threading
import time

b触发的时候top窗口应该还没有销毁
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 11:46

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表