Home > Software engineering >  Tkinter pack_forget() and destroy() don't work
Tkinter pack_forget() and destroy() don't work

Time:05-25

I have a problem with these two functions that don't work as expected. I want to use a selection form drop-down menù and based on the selection two different set of checkbox are displayed in the root window. To do so, I use this code:

    from tkinter import *
import tkinter as tk

def evaluation(form):
    form.pack_forget()
    form.destroy()
    form=Frame(root)
    GotPlatform=platform.get()
    for elem in PlatformOption[GotPlatform]:
        OptionButtonSel[elem]=Checkbutton(form, text=elem)
        OptionButtonSel[elem].pack()
    form.pack(fill="both", expand = 1)  

PlatformOption={'Option1':["option1-1","option1-2"],'Option2':["option2-1","option2-2"]}
OptionButtonSel={}

root = tk.Tk()
f1=Frame(root)
menuBar = tk.Menu(root)
menu1 = tk.Menu(root)
submenu = tk.Menu(root)
platform = StringVar()
submenu.add_radiobutton(label="Option1", value="Option1", variable=platform,command=lambda:evaluation(f1))
submenu.add_radiobutton(label="Option2", value="Option2", variable=platform,command=lambda:evaluation(f1))
menuBar.add_cascade(label="Options", menu=menu1)
menu1.add_cascade(label="Select option", menu=submenu)

root.config(menu=menuBar)
root.mainloop()

The code works but whenever I change the options fron drop-down menù, the checkboxes option are stacked and aren't overwritten as expected.

This puzzles me since I have used this other code and it works as expected:

from tkinter import Tk, Frame, Menu, Label



def show_frame1():
    forget_all()
    f1.pack(fill="both", expand = 1)  
    


def show_frame2():
    forget_all()
    f2.pack(fill="both", expand = 1)  
    


def forget_all():
    f1.pack_forget()
    f2.pack_forget()


root = Tk()
f1 = Frame(root)
f2 = Frame(root)
Label(f1, text="MENU SELECTED 1").pack()
Label(f2, text="MENU SELECTED 2").pack()
menubar=Menu(root)
subMenu=Menu(menubar, tearoff = 0)
menubar.add_cascade(label = 'MENU', menu=subMenu)
subMenu.add_command(label = 'SUBMENU1', command = show_frame1)
subMenu.add_command(label = 'SUBMENU2', command = show_frame2)
root.config(menu = menubar)


root.mainloop() 

Aside from addind destroy(), the usage of frame and pack_forget() seems identical to me.

I use Python 3.10.1, IDE Spyder last version, Windows 8.

CodePudding user response:

The root of the problem is that you create a form that never appears on the screen. You create it, but never call pack on it. You then pass this form to the function every time the button is clicked. In other words, you keep passing the original form, not the new one that is recreated.

The best solution is for your main code to call pack, place, or grid on the form, and then in the function you can delete the children of the form without deleting the form itself.

So, add the following shortly after creating f1:

f1.pack(fill="both", expand=True)

Next, modify evaluation to destroy the children rather than the form itself:

def evaluation(form):
    for child in form.winfo_children():
        child.destroy()

    GotPlatform=platform.get()
    for elem in PlatformOption[GotPlatform]:
        OptionButtonSel[elem]=Checkbutton(form, text=elem)
        OptionButtonSel[elem].pack()

CodePudding user response:

It gives the effect that it doesn't work because the widget is invisible to the screen. This topic however is further explained below

pack_forget() not working

Just to prove my theory I did some other research about the topic and https://www.geeksforgeeks.org/python-forget_pack-and-forget_grid-method-in-tkinter/ explains the concept of pack_forget() perfectly

  • Related