Im trying to check a checkbox and delete both 'checked box' and 'label' with upper button. They are both created in a loop from the same list. I've tried to build a dictionary with 'buttons' as key and 'result_of_checkboxes' as value and destroy key if value is different from ''. It doesnot work. If buttons are keys, why can't I destroy them? What is the correct approach? Thanks in advance!
from tkinter import *
root = Tk()
root.geometry('400x400')
def destroy_button():
for key, value in dict_check_and_buttons:
if value != '' and current_var != '':
key.destroy()
current_box.destroy()
my_friends = ['Donald', 'Daisy', 'Uncle Scrooge']
button1= tk.Button(root, text = "delete both if cbox is checked", command = destroy_button).pack()
#-----ild checkbuttons and store results in checkbutton_result list
checkbutton_result = []
for index, friend in enumerate(my_friends):
current_var = tk.StringVar()
current_box = tk.Checkbutton(root, text= friend,
variable = current_var,
onvalue = friend, offvalue = ""
)
checkbutton_result.append(current_var) #append on and off results
current_box.pack()
#-----build buttons and store them in buttons_list
buttons_list = []
for index, friend in enumerate(my_friends):
buttons= tk.Button(root, text = friend).pack()
buttons_list.append(buttons)
#-----build a dict with list to say "if onvalue != '' destroy button"
dict_check_and_buttons = dict(zip(buttons_list, checkbutton_result))
root.mainloop()
the error is:
Exception in Tkinter callback
Traceback (most recent call last):
File "c:\python\python38\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "<ipython-input-18-954d3a090f2c>", line 7, in destroy_button
for key, value in dict_check_and_buttons:
TypeError: cannot unpack non-iterable NoneType object
CodePudding user response:
There are following issues in your code:
- all items in
buttons_list
areNone
due to the following line:
buttons= tk.Button(root, text = friend).pack() # buttons is the result of pack()
The line should be split into two lines:
buttons = tk.Button(root, text=friend)
buttons.pack()
- you cannot get a (key, value) pair by iterating a dictionary:
for key, value in dict_check_and_buttons: # dict_check_and_buttons is a dictionary
...
Instead you should iterate on the result of dict_check_and_buttons.items()
:
for key, value in dict_check_and_buttons.items():
...
- you need to call
get()
on atk.StringVar()
:
for key, value in dict_check_and_buttons.items():
if value.get() != '': # use value.get()
key.destroy()
If you need to destroy the checkbutton as well, you need to save the checkbutton to checkbutton_result
along with its associated variable:
checkbutton_result = []
for index, friend in enumerate(my_friends):
current_var = tk.StringVar()
current_box = tk.Checkbutton(root, text= friend,
variable = current_var,
onvalue = friend, offvalue = ""
)
checkbutton_result.append((current_box, current_var)) # save both checkbutton and its associated variable
current_box.pack()
Then destroy the checkbutton inside destroy_button()
:
def destroy_button():
for btn, (cb, cbvar) in dict_check_and_buttons.items():
if cbvar.get() != '':
btn.destroy()
cb.destroy()
CodePudding user response:
With your answer I rebuild the code. It is perfect now thanks to you.
import tkinter as tk
root = Tk()
root.geometry('400x400')
'''
to get if checkbox is checked to use results to delete checkbox and label
'''
def destroy_button():
for key, value in dict_buttons.items():
if value.get() != 0:
key.destroy()
def destroy_box():
for key1, value1 in dict_box.items():
if value1.get() != 0: # and current_var.get() != 0:
key1.destroy()
my_friends = ['Donald', 'Daisy', 'Uncle Scrooge']
button1= tk.Button(root, text = "delete label if box is checked", command = destroy_button).pack()
button2= tk.Button(root, text = "delete box if box is checked", command = destroy_box).pack()
#-----ild checkbuttons and store results in checkbutton_result list
checkbutton_result = []
box_list = []
for index, friend in enumerate(my_friends):
# current_var = tk.IntVar()
current_var = tk.IntVar()
# current_var = tk.StringVar()
current_box = tk.Checkbutton(root, text= friend,
variable = current_var,
onvalue = 1, offvalue = 0
)
checkbutton_result.append(current_var) #append on and off results
current_box.pack()
box_list.append(current_box)
#-----build buttons and store them in buttons_list
buttons_list = []
for index, friend in enumerate(my_friends):
buttons= tk.Button(root, text = friend)
buttons.pack()
buttons_list.append(buttons)
#-----build a dict with list to say "if onvalue != '' destroy button"
dict_buttons = dict(zip(buttons_list, checkbutton_result))
dict_box =dict(zip(box_list, checkbutton_result))
root.mainloop()