r_czw20
r_czw20

Reputation: 41

How does destructor work when closing a Tkinter toplevel widget?

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

Answers (1)

Muhammad Hamza Naveed
Muhammad Hamza Naveed

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

Related Questions