Reputation: 41
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?
Upvotes: 3
Views: 61
Reputation: 26
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!
Upvotes: 1