0

I am using tkinter to make a GUI. I want some widgets to appear only if some parameters are chosen. I have used the method .pack_forget() for this. However, now I have another issue. I made a condition on an OptionMenu that will make appear wheather a ComboBox or an Entry, depending on what chose the user. But I cannot manage to make one of the two widgets disappears if the user changes his choice.

Here is my code:

# Creation of Frame 4 #

Frame4 = tk.Frame(fenetre)
Frame4.pack(anchor = tk.NW, padx = 5, pady = 5)

# label4 creation #

label4 = tk.Label(Frame4, text = "what is the format?", font = ('Arial', '12'))
label4.pack(side = tk.LEFT)

# Création de la commande #

def Format_choice(self):

   global Format

   if choice.get() != Format:
      Format = choice.get()
    
   if Format == "CAPS Client":
    
      # Création de la liste déroulante
      Frame6.pack(anchor = tk.NW, padx = 5, pady = 5)

      # NOMS is a list of strings
      comboExample = ttk.Combobox(Frame6, textvariable = tk.StringVar(), values = NOMS, width = 45)
                    
      comboExample.current(0)

      def callbackFunc(self):
          global nom_site
          nom_site = comboExample.get()

      comboExample.bind("<<ComboboxSelected>>", callbackFunc)

      comboExample.pack(side = tk.LEFT)


   elif Format == "ETUDE":
        
      Frame6.pack(anchor = tk.NW, padx = 5, pady = 5)
        
      site = tk.StringVar()

      def Name():

         global nom_site
         nom_site = site.get()


      entrysite = tk.Entry(Frame6, textvariable = site)
      entrysite.pack(side=tk.LEFT, padx=5, pady=5)
      entrysite.focus_set()
        
      valider = tk.Button(Frame6, text="Confirmer", command = Name, activeforeground = 'red')
      valider.pack(side = tk.LEFT)
    

# Creation of choice#      
    
choice = tk.StringVar()
choice.set("Default")


# Creation of the OptionMenu #

option4 = tk.OptionMenu(Frame4, choice, "Format1", "Format2", command = Format_choice)
option4.pack(side = tk.LEFT)

# Creation of Frame6 

Frame6 = tk.Frame(fenetre)

# label6 creation

label6 = tk.Label(Frame6, text= "What is the name of the site ?", font = ('Arial', '12'))

label6.pack(side=tk.LEFT)

Frame6.pack_forget()
Jorisltc
  • 15
  • 7
  • Can you please use better variable names? Right now you have a variable named `FORMAT` and another one named `Format`. Also you have a variable `site` that isn't really used. Also nested functions isn't advisable. Also please look at [PEP 8](https://www.python.org/dev/peps/pep-0008/) – TheLizzard Jun 16 '21 at 14:07
  • 2
    _"But I cannot manage to make one of the two widgets disappears if the user changes his choice."_ why can't you? What happens when you try? – Bryan Oakley Jun 16 '21 at 14:07
  • @TheLizzard yes, I agree it is not really clear i'm going to fix this – Jorisltc Jun 16 '21 at 14:11
  • @BryanOakley When I try, if I choose "Format1", a Combobox is created but then if I change my mind and choose "Format2", an Entry is created next to the Combobox. – Jorisltc Jun 16 '21 at 14:13
  • I tried using ComboExample.destroy() or entrysite.destroy() in the beginning of the respective loops but if they do not already exist it doesn't work. Also tried, using a condition with winfo_exists() – Jorisltc Jun 16 '21 at 14:15
  • code edited, hope it will be more clear – Jorisltc Jun 16 '21 at 14:31

1 Answers1

0

pack_forget() only makes the Frame6 invisible here, while it is still there. So, use .destroy() instead. As beautifully answered here:

Python Tkinter clearing a frame

So, basically you have two options:

  1. Destroy the Frame6 and again create everything inside it in each if-elif case of function Format_choice() , OR
  2. Destroy every widget of Frame6 created by the previously selected option.

If you like the second way, here is a piece of code you can add before your if-elif case. Using winfo_children() works like a charm:

.
.
def Format_choice(self):
   global Format

   if choice.get() == Format:
      return   #so that if user selects same option again, no change occurs in Frame6
   else:
      Format = choice.get()

   for widget in Frame6.winfo_children():
        if widget != label6:
            widget.destroy()
            
   if Format == "CAPS Client":
      # Création de...
   .
   .
   .

This way, your label6 which you probably don't want to destroy, is not destroyed, while other widgets get destroyed.

Kartikeya
  • 818
  • 2
  • 6
  • 11
  • One thing I want to point is, your OptionMenu has choices "Format1" and "Format2", but your function uses values "CAPS Client" and "ETUDE" for conditions, so I hope you will clear that up. – Kartikeya Jun 17 '21 at 02:40
  • Thank you so much, it works totally the way I wanted ! I clear it up yes ! – Jorisltc Jun 17 '21 at 12:36