Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

tkinter: cleanly destroy auto-wrapping widgets created in tk.Text with window_create

Based on this answer, I successfully created my own widget where labels are wrapped automatically in a Text element using window_create.

I’m also able to destroy these labels using nametowidget. However, the window element of the deleted widgets remains and is returned by dump.

Here is my minimal reproducible example:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import tkinter as tk

root = tk.Tk()

btn_frame1 = tk.Frame(root)
btn_frame1.pack(side='top', fill='x')
create_labels_btn = tk.Button(btn_frame1, text='Create Labels')
create_labels_btn.pack(side='left')
delete_labels_btn = tk.Button(btn_frame1, text='Delete Labels')
delete_labels_btn.pack(side='right')

label_text_field = tk.Text(root, height=7, width=40)
label_text_field.pack(side='top')

dump_text_field_btn = tk.Button(root, text='Dump text field')
dump_text_field_btn.pack(side='top')

dumping_text = tk.Text(root, height=7, width=40)
dumping_text.pack(side='top')

def create_labels():
    for i in range(1, 7):
        lbl = tk.Label(label_text_field, width=12, text=f'label {i}')
        label_text_field.window_create("insert", window=lbl, padx=8, pady=8)

create_labels_btn['command'] = create_labels

def delete_labels():
    for lbl in label_text_field.dump("1.0", "end"):
        if lbl[0] =='window' and lbl[1]:
            label_text_field.nametowidget(lbl[1]).destroy()

delete_labels_btn['command'] = delete_labels

def dump_text_field():
    dumping_text.delete("1.0", "end")
    for obj in label_text_field.dump("1.0", "end"):
        dumping_text.insert('end', str(obj) + '\n')

dump_text_field_btn['command'] = dump_text_field

root.mainloop()

After creating and deleting my labels. The deleted elements are still visible in the dump output (the widget was succesfully deleted though and the remaining name is only an empty string):

enter image description here

How can I cleanly remove the associated window so that they don’t add up over time?

>Solution :

You need to remove the items from the Text widget using the index returned by .dump(). But you need to remove them in reverse order, otherwise the index will be wrong after removing the first item.

def delete_labels():
    for lbl in label_text_field.dump("1.0", "end")[::-1]:  # get the items in reverse order
        if lbl[0] =='window' and lbl[1]:
            label_text_field.nametowidget(lbl[1]).destroy()
            label_text_field.delete(lbl[2]) # remove item from text box as well

Actually you can pass window=1 to dump() to return window items only:

def delete_labels():
    for lbl in label_text_field.dump("1.0", "end", window=1)[::-1]:
        if lbl[1]:
            label_text_field.nametowidget(lbl[1]).destroy()
            label_text_field.delete(lbl[2])
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading