#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) великолепно и захватывающе!