как удалить как флажок, так и метку, если установлен флажок

#python #for-loop #tkinter #checkbox #destroy

Вопрос:

Я пытаюсь установить флажок и удалить как «флажок», так и «метку» с помощью верхней кнопки. Они оба создаются в цикле из одного и того же списка. Я попытался создать словарь с «кнопками» в качестве ключа и «флажками result_of_ «в качестве значения и уничтожить ключ, если значение отличается от «. Это не работает. Если кнопки-это ключи, почему я не могу их уничтожить? Каков правильный подход? Заранее спасибо!

 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()     

ошибка в том, что:

 Exception in Tkinter callback Traceback (most recent call last):  File "c:pythonpython38libtkinter__init__.py", line 1892, in __call__  return self.func(*args)  File "lt;ipython-input-18-954d3a090f2cgt;", line 7, in destroy_button  for key, value in dict_check_and_buttons: TypeError: cannot unpack non-iterable NoneType object  

Комментарии:

1. Ваш buttons_list — это просто список , полный None s — результатов вызова .pack() , а не самих виджетов. Вам нужно сделать .pack() это отдельно, так же, как вы делали в checkbutton_result цикле.

Ответ №1:

В вашем коде есть следующие проблемы:

  • все входящие товары buttons_list None должны быть указаны в следующей строке:
 buttons= tk.Button(root, text = friend).pack() # buttons is the result of pack()  

Строка должна быть разделена на две строки:

 buttons = tk.Button(root, text=friend) buttons.pack()  
  • вы не можете получить пару (ключ, значение), выполнив итерацию словаря:
 for key, value in dict_check_and_buttons: # dict_check_and_buttons is a dictionary  ...  

Вместо этого вы должны повторить результат dict_check_and_buttons.items() :

 for key, value in dict_check_and_buttons.items():  ...  
  • вам нужно позвонить get() по tk.StringVar() :
 for key, value in dict_check_and_buttons.items():  if value.get() != '': # use value.get()  key.destroy()  

Если вам также нужно уничтожить кнопку проверки, вам необходимо сохранить кнопку проверки checkbutton_result вместе с связанной с ней переменной:

 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()  

Затем уничтожьте контрольную кнопку внутри destroy_button() :

 def destroy_button():  for btn, (cb, cbvar) in dict_check_and_buttons.items():  if cbvar.get() != '':  btn.destroy()  cb.destroy()  

Комментарии:

1. Уважаемый г-н ACW1668 большое вам спасибо, для меня это новые актуальные концепции.

Ответ №2:

С вашим ответом я перестраиваю код. Теперь это прекрасно благодаря вам.

 import tkinter as tk  root = tk.Tk() root.geometry('400x400') ''' to get if checkbox is checked to use results to delete checkbox and label '''   def destroy_button_box():  for button_names, (ckbox, on_off) in dict_buttons_box_var.items():  if on_off.get() != 0:  button_names.destroy()  ckbox.destroy()     my_friends = ['Donald', 'Daisy', 'Uncle Scrooge']  button1 = tk.Button(root, text="delete label if box is checked", command=destroy_button_box).pack()   checkbox_variable_list = []  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  )   current_box.pack()    # append checkbox and 'on' or 'off' results  checkbox_variable_list.append((current_box, current_var))  # -----build buttons and store them in buttons_list buttons_list = [] for index, friend in enumerate(my_friends):  button_names = tk.Button(root, text=friend)  button_names.pack()    # append buttons in loop  buttons_list.append(button_names)  # -----build a dict with lists to use in destroy_box_button function: dict_buttons_box_var = dict(zip(buttons_list, checkbox_variable_list))  root.mainloop()  

Комментарии:

1. Оба в одной и той же функции еще лучше, еще раз спасибо. btn.destroy() cb.destroy() и (cb, cbvar) великолепно и захватывающе!