简体   繁体   中英

Tkinter. How to destroy the root window while top level window is waiting for a variable

I have an issue whereby a user can open a top_level window which sits waiting for a variable via the wait_variable() method. But while the top_level window is open, the root window is still visible and the user is able to close the root window via usual methods (this is intentional). What I'd like (and sort of expect tkinter to do) is that calling .destroy() or .quit() on the root window will cause all of root 's children to be terminated. But what appears to be happening is that the top_level window remains stuck in its local event loop and can only be killed via the task manager once its parent has gone.

So what am I doing wrong? How do I get the top_level window to listen out for it's parents destruction while its in a local event loop?

.

Below is some example code that demonstrates the issue. If you run the code and follow the steps below your IDE WILL CRASH!! probably, so save you work. Push the Click button in root. The top level window will appear with another button that says Test . Now close the root window. The IDE will hang.

import tkinter
root = tkinter.Tk()
def toplevel(event=None):
    def set1(event=None):
        vr.set(1)
    tp = tkinter.Toplevel(root)
    vr = tkinter.IntVar()
    bt_ = tkinter.Button(tp,text='Test',command=set1)
    bt_.grid()
    tp.wait_variable(vr)
    tp.destroy()
bt = tkinter.Button(root,text='Click',command=toplevel)
bt.grid()
root.mainloop()

Edit: My current solution is to repoint the WM_DELETE_WINDOW protocol when the top_level window starts, to a function that sets the variable that the local event loop is waiting for, and then destroys the root window.

The correct solution IMO is to not wait on the variable, but rather, wait on the window. Your button then must take on the responsibility of destroying the window instead of or in addition to setting the variable.

This is the right solution for another reason: as written your program will also hang if the user destroys the toplevel with the buttons in the titlebar. Since you're waiting on a variable, because the window is destroyed the variable will never be set.

(the solution you proposed in your edit is also valid -- register with WM_DELETE_WINDOW on the toplevel to set the variable when the window is destroyed. The effect will be the same).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM