I am trying to generate checkbuttons based on radiobutton selection using Tkinter in Python. Here are the dictionaries; the keys should show as checkbuttons:
PERISHABLE_OPTIONS = {'Vegetables': 0, 'Fruits': 0, 'Bread': 0, 'Dairy': 0, 'Meat': 0, 'Other': 0}
NONPERISHABLE_OPTIONS = {'Books': 0, 'Clothes': 0, 'Dry Food': 0, 'Household': 0, 'Sanitary': 0, 'Other': 0}
Here is the code that shows the radiobuttons and calls the method for the checkbuttons:
class FormInput(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Choose your donations!", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
style = Style(self)
style.configure("TRadiobutton", font=("Calibri", 18))
category_of_donation = {"Perishable": "1", "Non-Perishable": "2"}
var = tk.StringVar()
for text, value in category_of_donation.items():
r = Radiobutton(self, text=text, variable=var, value=value, command=lambda: controller.show_checkbox(var))
r.pack(anchor=CENTER, padx=5, pady=5)
submit_button = tk.Button(self, text="Submit", command=lambda: controller.show_frame("PageTwo"))
submit_button.pack()
And here is the method for showing checkbuttons:
def show_checkbox(self, v):
if v.get() == '1':
for i in PERISHABLE_OPTIONS:
PERISHABLE_OPTIONS[i] = IntVar()
c = Checkbutton(self, text=i, variable=PERISHABLE_OPTIONS[i])
c.pack(anchor="center", padx=5, pady=5)
elif v.get() == '2':
for i in NONPERISHABLE_OPTIONS:
NONPERISHABLE_OPTIONS[i] = IntVar()
c = Checkbutton(self, text=i, variable=NONPERISHABLE_OPTIONS[i])
c.pack(anchor="center", padx=5, pady=5)
My issue is the checkbuttons keep appearing every time I click on the radiobuttons. For example, I will click on the radiobutton that says Perishable, and it will give me the list of checkbuttons I want (Vegetables to Other). But when I toggle, it shows the list attributing to Non-Perishable (Books and onwards), but it will still show the Perishable list too. Here is a screenshot:
I'm surely missing something but I cannot figure it out. Can someone help me please? Thank you!
As @Henry Yik said, you shouldn't recreate all the checkbuttons every time you want to show them; 1) because it's easier to write that doesn't recreate them, and 2) because code that does recreate them will be much slower than code that doesn't.
As usual, I'll explain everything, but if you want to skip the explanations, at the bottom will be a (minimalized) working example.
Creating the checkbuttons
First, in order to make it so that the checkbuttons can be packed and pack_forgotten, they need to be created. For your purposes, it's simplest to use a
for
loop to create the checkbuttons, and then add them to a list. Here's an example for creating the perishable checkbuttons:As you can see, this simply loops through all the keys in
PERISHABLE_OPTIONS
, and creates checkbuttons based on them, in much the same way as you did in your code. The only difference is that the checkbuttons are stored in a list calledself.perishables
for later use. You can do the same for the non-perishable checkbuttons.Packing/unpacking the checkbuttons
Now that you've created a list for each type of checkbutton, you need to know how to pack/unpack them. We'll do that by checking which radio button is selected (which you've already done), and then:
pack_forget()
method.pack()
method, with the appropriate arguments.Here is an example that does just that, unpacking the non-perishable checkbuttons and packing the perishable checkbuttons:
Showing the checkbuttons when the app starts
You might notice that, when the app starts, neither radiobutton will be selected, so neither list of checkbuttons will be shown. We can solve both these problems simultaneously by setting an initial value for the radiobuttons'
var
, like this:This code will have the perishables selected first. If you want to show the non-perishables first, just change
tk.StringVar(value="1")
totk.StringVar(value="2")
.The final code
Alright, now that all that's said, here is a simplified working example based off of your code: