Why isn't root.quit() or root.destroy() working but only the combination of both?

Related searches

In my program I implemented a Popup with some entries for user input. That Popup has an 'Enter' button to confirm and collect the input and then close the Popup automatically. For closing the Popup I found the root.destroy() and root.quit() methods (in my code self.master instead of root). I thought I kind of understand how to use them but apparently I didn't. :/

import tkinter as tk


root = tk.Tk()
window = MainWindow(root)
root.mainloop()


class MainWindow(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.pack()

        #some irrelevant widgets

        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()


    def new_element(self):

        root = tk.Toplevel()
        popup = Pupup(root, someData, otherData)
        root.mainloop()

        #do some other stuff



class Popup(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some widgets

        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a, b))
        btn.pack()


    def foo(self, a, b):

        #do something with widget data

        self.master.quit()
        self.master.destroy()

In foo() first I only used destroy(). It closes the Popup but the program didnt continue with the code in new_element(). (It seemed as if the mainloop() was still looping.) Using quit() produced the opposite result: the rest of the code in new_element() was executed but the Popup was still there. Only using quit() and destroy() in that particular order gave me the result I wanted.

According to thousands of examples on the internet it should be possible using only one of the two methods. Why isn't it working in my code?

EDIT: deleted var1 and var2 from the MainWindow constructor (copy and paste mistake during creation of this question.

EDIT: Also I get the feeling the the problem might be the scope of the root varibale. In new_element() do I create a local variable called root or do I overwrite the global root variable?

The root of the problem is that you're calling mainloop more than once. You should not do that. It causes problems very much like the one that you're having.

If your goal is to create a popup window, and then wait for the user to dismiss the popup window, tkinter has a method specifically for that. It's called wait_window, and it won't return until the window it is waiting on has been destroyed.

top = tk.Toplevel()
popup = Popup(top, "some data", "other data")
top.wait_window(top)        

You can put additional code after top.wait_window(top), and it won't execute until the popup has been destroyed.

Within your popup code, your button simply needs to call destroy on the popup window. You shouldn't call quit.

def foo(self, a, b):

    #do something with widget data

    self.master.destroy()

Why Isn't Netflix Working, Why isn't Netflix working? If Netflix isn't working, you may be experiencing a network connectivity issue, an issue with your device, or an issue� Black D.C. residents fought to change their city’s unequal status during the civil rights movement, and won some key victories.The first was the right to vote for the president and vice

There are many things wrong with your example (copy paste not working), but after arranging things to work (giving values and stuff), here is your problem:

    def new_element(self):
        root = tk.Toplevel()
        popup = Pupup(root, someData, otherData)
        # root.mainloop() # < ------ This generates a new main loop, with is destroyed.

here is a complete code that works:

import tkinter as tk


class Popup(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some widgets

        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a, b))
        btn.pack()


    def foo(self, a, b):

        #do something with widget data

        self.master.quit()
        # self.master.destroy()


class MainWindow(tk.Frame):

    def __init__(self, master, var1, var2):

        tk.Frame.__init__(self, master)
        self.pack()

        #some irrelevant widgets

        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()


    def new_element(self):

        root = tk.Toplevel()
        popup = Popup(root, 'a', 'b')
        # root.mainloop()

        #do some other stuff

root = tk.Tk()
window = MainWindow(root,1,2)
root.mainloop()

Why isn't Berkeley air quality impacted by red, smoky skies today?, Strong winds are pushing smoke from the August Complex fires about 5000 feet up in the air through a process called "turbulent mixing." So why isn’t the UP part of Wisconsin? It's a question on many people's minds. It's also WHYsconsin’s most-asked question. But this isn’t a story about a bloody battle where Michigan reigned supreme.

I believe the problem is you have created a second loop, to fix this you can just remove the second loop, and then the .destroy() function should work just fine.

Like this

class MainWindow(tk.Frame):
    def __init__():
        # your init code

    def new_element(self):
        root = tk.Toplevel()
        popup = Popup(root, 1, 0)

class Popup(tk.Frame):

    def __init__(self, master, var1, var2):
        # your init code

    def foo(self, a, b):
        self.master.destroy()

Another comment I will make is that I believe the way you have structured this windows is misleading, and could cause confusion (keep in mind this is just preference and is no longer about "real" problems).

I believe instead of having a Popup(Frame) class, you should create a Popup(Toplevel) class.

Like this

import tkinter as tk

class MainWindow(tk.Frame):

    def __init__(self, master):

        tk.Frame.__init__(self, master)
        self.pack()
        btn_new_element = tk.Button(self, text='new', command=self.new_element)
        btn_new_element.pack()
        self.master = master
        self.pack()

    def new_element(self):
        popup = Popup(self.master, 1, 0)


class Popup(tk.Toplevel):
    def __init__(self, master, var1, var2):
        super().__init__(master)
        #some widgets
        btn = tk.Button(self, text='Enter', command=lambda a=var1, b=var2: self.foo(a,b))
        btn.pack()

    def foo(self, a, b):
        self.destroy()

if __name__ == '__main__':
    root = tk.Tk()
    window = MainWindow(root)
    root.mainloop()

When you create a Toplevel element it needs a master, the master will be the main window in this instance. When you use self.destroy within the Toplevel class, you are not destroying the Toplevels master, but instead you are destroying the Toplevel itself.

Why isn't there a 'Q' hurricane name?, We are about to run out of names for the 2020 hurricane season and move on to the Greek Alphabet -- but why aren't some letters used in the� On the ultraprocessed diet, the subjects on average consumed 500 more calories a day and gained two pounds. A possible reason: The participants’ levels of PYY, a hormone that suppresses appetite

Why Isn't My Brain Working?: A revolutionary , Amazon.com: Why Isn't My Brain Working?: A revolutionary understanding of brain decline and effective strategies to recover your brain's health eBook:� As other cities go into lockdown, why isn’t London having a second wave? Experts suggest the capital’s previous exposure, and capacity to embrace home working, may now be inhibiting the virus .

Why Isn't My Brain Working?: A Revolutionary Understanding of , Why Isn't My Brain Working?: A Revolutionary Understanding of Brain Decline and Effective Strategies to Recover Your Brain's Health: 8601420672192:� Why Isn't California Criticized Like Florida on Covid-19? It’s a blue state, of course. But the virus doesn’t discriminate based on party affiliation. By . Joe Nocera,

Why Isn't My Printer Printing? 6 printing issues you can fix. by. Tom Nelson. Writer. Tom Nelson is an engineer, programmer, network manager, and computer network and

Comments
  • This code won't work as-is because you're trying to create an instance of MainWindow before you've defined the class.
  • This seems like the solution you need @Maxxx
  • This answer would be much better if you added some explanation outside of the code. Without an explanation, we must compare your code line-by-line and character-by-character with the original to see what has changed, and then try to figure out which changes were necessary to solve the problem and which were just personal preferences.
  • Look at the EDIT, I guess this is why you couldn't run the code. But still this is not the solution of my problem because with your code quit() not only closes the Popup but the MainWindow as well.
  • I believe that the answer is to remove the second loop, root.mainloop(), that you create and to then use root.destroy() to close the Toplevel window you created.
  • @MatthewGadsden this creates again the problem that the #doSomeOtherStuff-code in new_element() isn't executed until I click the 'new'-button in the MainWindow again.
  • @Maxxx I see yes. For #doSomeOtherStuff in new_element() do you need data from the new window created for the code to run?`
  • Changing Popup(tk.Frame) to Popup(tk.Toplevel) somehow creates a empty Popup in addition to the one is supposed to pop up. However @BryanOakley 's solution works fine.
  • This would be because you didn't remove the line root = tk.Toplevel() from new_element() which would mean you would create two Toplevel elements, root = tk.Toplevel() and the Popup(tk.Toplevel)
  • This way the MainWindow and the Popup share the same master, so both windows are destroyed.
  • This is not how a Toplevel() element works, the top levels master is the main window, but you destroy the toplevel with self.destroy(), you don’t destroy the toplevel’s master. The code I provided should work find if you just copy and paste it into a blank document.