Home > Enterprise >  tkinter how delete both checkbox and label if checked box
tkinter how delete both checkbox and label if checked box

Time:11-09

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 are None 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 a tk.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()
  • Related