0

When closing an instance of the ChildWindow class, which was called from another instance of MainWindow, the code does not continue to be executed.

I noticed that only when the MainWindow instance is closed does it continue to run. In general, it has a cumulative property, so the number of times the ChildWindow closes the window, the continuation will be displayed.

I want the function to continue executing when the ChildWindow closes, without closing the main window. Here's my code:

from tkinter import *

class MainWindow():

    def __init__(self):
        self.root = Tk()
        
    def run(self):
        Button(self.root, text='click', command=lambda:self.open_child_window()).pack()
        self.root.mainloop()

    def open_child_window(self):
        A = ChildWindow()
        A.run()
        print("why i'm not write?")

class ChildWindow():

    def __init__(self):
        self.root = Toplevel()

    def run(self):
        self.root.mainloop()


A = MainWindow()
A.run()

It seems to me that this is due to the self.root.mainloop() loop, so I was looking for how to stop it, the .quit(), .destroy() methods do not help.

Ben the Coder
  • 539
  • 2
  • 5
  • 21
  • 4
    You shouldn't be calling `Tk()` more than once - that creates the entire GUI environment (with limitations on how those environments can interact with each other), not just a window. You want `Toplevel()` for that. – jasonharper Feb 07 '23 at 14:52
  • @jasonharper, this doesn't work either :( – chikibamboni Feb 07 '23 at 14:56
  • 3
    You should also be running *one* event loop. – chepner Feb 07 '23 at 14:59
  • @chepner, I ran into the same problem. Intended .mainloop() prevents further execution – chikibamboni Feb 07 '23 at 15:05
  • 1
    You should be able to continue with calling `self.root.quit()` from a button for example. Anyway, there is `wait_window` or `wait_variable` for this taks but be aware of what it does. https://stackoverflow.com/questions/74370984/is-tkwait-wait-variable-wait-window-wait-visibility-broken – Thingamabobs Feb 07 '23 at 15:11
  • @chepner, FYI, a nested loop is fine. See my answer. – relent95 Feb 08 '23 at 03:01
  • 1
    As an aside: writing `lambda: x()` is like writing `[x][0]` - either way, just write `x` instead. `lambda` is for when the function needs to be adapted (i.e., change the parameters, by ignoring some of what is passed in or by calculating more things to pass). – Karl Knechtel Feb 08 '23 at 03:06

1 Answers1

1

It's called a nested event loop or modal loop. Use the mainloop() and quit() like this.

class ChildWindow():
    def __init__(self):
        self.root = Toplevel()

    def run(self):
        win = self.root
        def on_close():
            win.destroy()
            win.quit()
        win.protocol('WM_DELETE_WINDOW', on_close)
        win.mainloop()
        print('end of the nested loop')
...

You can also use wait_window() and destroy() like this.(The former runs a nested event loop until the window is destroyed.)

class ChildWindow():
    ...
    def run(self):
        win = self.root
        def on_close():
            win.destroy()
        win.protocol('WM_DELETE_WINDOW', on_close)
        win.wait_window()
relent95
  • 3,703
  • 1
  • 14
  • 17
  • I was already told about the `wait_window` method, but this method also works. Somehow I'm even surprised that it works, because I already tried it. But anyway, thanks :D – chikibamboni Feb 09 '23 at 16:53
  • apparently it's all about the `win.destroy` and `win.quit` methods, because I tried to use them separately... – chikibamboni Feb 09 '23 at 16:59
  • A solution using the ```wait_window()``` was added. Thanks. – relent95 Feb 10 '23 at 01:01