I'm trying to understand what happens when you close a toplevel window, specifically, at what point it becomes unreferenced and eligible for garbage collection.
I have put together the code below and this works as I would expect. You open the toplevel with the button, close the toplevel with the cross in the corner and the destructor executes its code.
from tkinter import *
from tkinter import ttk
class TestClass(Toplevel):
def __init__(self, *args, **kwargs):
Toplevel.__init__(self, *args, **kwargs)
self.title('A New Window')
print ('window created')
def __del__(self):
print('destructor called')
def AButtonPress():
#create a device window
new_window = TestClass(root)
root.wait_window(new_window)
print("window closed")
root = Tk()
a_button=ttk.Button(root,text="Press Me",command=AButtonPress)
a_button.grid(column=0, row=0)
root.mainloop()
However, when I add any widgets to the toplevel, say for example a label, when you close the toplevel, the destructor is no longer called.
from tkinter import *
from tkinter import ttk
class TestClass(Toplevel):
def __init__(self, *args, **kwargs):
Toplevel.__init__(self, *args, **kwargs)
self.title('A New Window')
print ('window created')
#create a widget
self.a_label=ttk.Label(self,width=15,text = "A Label")
self.a_label.grid(column=0, row=0)
def __del__(self):
print('destructor called')
def AButtonPress():
#create a toplevel object
new_window = TestClass(root)
root.wait_window(new_window)
print("window closed")
root = Tk()
a_button=ttk.Button(root,text="Press Me",command=AButtonPress)
a_button.grid(column=0, row=0)
root.mainloop()
Does this now mean that the toplevel will no longer get garbage collected and repeated opening and closing of the toplevel will consume memory?
Am I looking too much into this?
Here is some demo code that deletes all the children of a Toplevel and enforces the garbage collector to remove them from memory:
import tkinter as tk
root = tk.Tk()
def on_closing():
for child in newwin.winfo_children():
child.destroy() # Remove them from the window
del(child) # Enforce garbage collector
newwin.destroy()
def open_window():
global newwin
newwin = tk.Toplevel()
newwin.protocol("WM_DELETE_WINDOW", on_closing) # Override window close action
tk.Label(newwin, text="this is a child element").pack()
tk.Button(text="Open Toplevel", command=open_window).pack()
root.mainloop()
You can use code like this to ensure your toplevels do not consume any program memory once the toplevels outlive their usefulness. Let me know if this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With