In Python using tkinter
, what is the difference between root.destroy()
and root.quit()
when closing the root window?
Is one pr
root.quit()
causes mainloop to exit. The interpreter is still intact, as are all the widgets. If you call this function, you can have code that executes after the call to root.mainloop()
, and that code can interact with the widgets (for example, get a value from an entry widget).
Calling root.destroy() will destroy all the widgets and exit mainloop. Any code after the call to root.mainloop()
will run, but any attempt to access any widgets (for example, get a value from an entry widget) will fail because the widget no longer exists.
The tkinter.Tk "quit" method exits the "mainloop" event-handler, and "destroy" destroys all the embedded widgets and only then exits the "mainloop". So is "destroy" the better of the two? Well, sometimes not. If "destroy" fails to destroy all the widgets for some reason, then "mainloop" is never exited and Python locks up. It can be better to just let Python shut things down in an orderly manner at the end of the script.
For example, if you embed a Matplotlib plot in a Tkinter window, that is useful because Matplotlib's own widgets are somewhat clunky to use. Unfortunately, if you then try to close the window by clicking the usual "X" in the title-bar, the window closes alright but leaves Python running. If the script had been started from a terminal, you'd have to mash Ctrl-C for a couple of minutes to get the prompt back. The reason being that the window-close event is bound to "destroy" which does not destroy the Matplotlib objects but leaves them orphaned.
The fix is to bind the window-close event to "quit" instead. But... if the script is started in a Tkinter-based IDE like IDLE, then that creates a new problem in that the window does not close because IDLE holds Tkinter running. So now "destroy" must be added after the mainloop. Finally, all is well.
Below is a minimal example of a Matplotlib plot that can be inverted with a press of a Tkinter button. Its window can be closed without problems. But if the windows-close event had been bound to "destroy" instead of "quit" then a locked-up Python process would remain.
#!/usr/bin/env python3
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
root = tk.Tk()
data, = plt.plot([0,5,3,4,-5,3])
canvas = FigureCanvasTkAgg(plt.gcf(), master=root)
invert = lambda: (data.set_ydata(-data.get_ydata()), canvas.draw())
tk.Button(master=root, text="Invert", command=invert).pack()
canvas.get_tk_widget().pack(fill=tk.BOTH, expand=1)
root.protocol("WM_DELETE_WINDOW", root.quit)
root.mainloop()
root.destroy()
Edit: I'll add that by binding the window-close event to both methods, you can avoid adding a line after the "mainloop", should that be desirable for some reason:
root.protocol("WM_DELETE_WINDOW", lambda: (root.quit(), root.destroy()))
My experience with root.quit()
and root.destroy()
...
I have a dos python script, which calls a tkinter
script (to choose from set of known values from combobox), then returns to the dos script to complete other things.
The TKinter script I've added onto the parent script. I may convert all to tkinter, but a combo works for the time being. It works in the following way:
To get rid of the windows box after selection was implemented, I needed to
1) root.quit()
inside the callback function where all my keypresses were being processed.
2) root.destroy()
after mainloop to destroy the windows box.
If I used root.destroy()
inside the callback, I got an error message saying tkinter objects were no longer accessable.
Without the root.destroy()
after mainloop, the windows box STAYED ONSCREEN until the whole parent script had completed.
quit()
stops the TCL interpreter. This is in most cases what you want, because your Tkinter-app will also stop. It can be a problem, if you e.g. call your app from idle. idle is itself a Tkinker-app, so if you callquit()
in your app and the TCL interpreter gets terminated, idle will also terminate (or get confused ).
destroy()
just terminates the mainloop and deletes all widgets. So it seems to be safer if you call your app from another Tkinter app, or if you have multiple mainloops."
taken from http://www.daniweb.com/forums/thread66698.html