Search code examples
pythontkintercheckbox

tkinter - show text/buttons/entry when checkbutton is checked and hide them when checkbutton is unchecked


I'm currently making a small application where I want the user to input some data, but there is an optional input. I want to use a checkbutton for that. If it is checked, the UI should show more input boxes and if it is unchecked, then the UI should hide them.

I'm using the newest version of anaconda-spyder and set the graphic backend in spyder to be tkinter

This is what I tried so far:

import tkinter as tk

window=tk.Tk()
frame_a=tk.Frame(window)
frame_b=tk.Frame(window)
frame_c=tk.Frame(window)

entry1=tk.Entry(frame_a, width=10)
entry1.pack()

var1=tk.IntVar()
checkbtn=tk.Checkbutton(frame_b, text="more options?", variable=var1, onvalue=1, offvalue=0)
checkbtn.pack(side=tk.TOP)

if var1.get() ==1:
   entry2=tk.Entry(frame_c, width=10)
   entry2.pack()
   
   frame_a.pack()
   frame_b.pack()
   frame_c.pack()
   
else:
    frame_a.pack()
    frame_b.pack()
window.mainloop()

I assumed that the state of the checkbutton gets checked within the mainloop, but it seems to only get checked at the start of the program.

Alternatively if the checkbutton is unchecked the other option could be grayed out/not interactable, but still visible (i don't know if that makes it easier or not)


Solution

  • In order to trigger a callback from a Checkbutton, you need to pass a function in via the command argument. That function will then be called whenever the checkbox changes state.

    To show or hide a given widget, you'd use pack or pack_forget respectively.

    Here I've set up a callback function called toggle_options which will programmatically show or hide frame_c depending on the state of checkbtn. I've also changed the type of var1 to a BooleanVar as that's a more sensible option (IMHO) for something with only two possible states.

    import tkinter as tk
    
    
    def toggle_options() -> None:
        if var1.get():
            frame_c.pack()  # show the frame
        else:
            frame_c.pack_forget()  # hide the frame
    
    
    window = tk.Tk()
    frame_a = tk.Frame(window)
    frame_b = tk.Frame(window)
    frame_c = tk.Frame(window)
    
    frame_a.pack()
    frame_b.pack()
    
    entry1 = tk.Entry(frame_a, width=10)
    entry1.pack()
    entry2 = tk.Entry(frame_c, width=10)
    entry2.pack()
    
    var1 = tk.BooleanVar()
    checkbtn = tk.Checkbutton(
        frame_b, 
        text="more options?", 
        variable=var1, 
        command=toggle_options,  # set the callback function here
    )
    checkbtn.pack()
    
    window.mainloop()