Tkinter ListBox报错:'StringVar'对象不可迭代问题求助
Tkinter ListBox更新失败及报错修复
问题场景
开发派对游戏Python版本,用tkinter构建GUI,包含卡组类型单选按钮和显示卡组名称的ListBox:
- 命令行中能正常获取卡组列表,但GUI加载时仅显示第一个卡组名称
- 点击单选按钮时控制台报错:
TypeError: 'StringVar' object is not iterable
相关代码
master_deck_list = [] deck_type_selection = tk.StringVar(value="official") with open('cah-cards-full.json', encoding="utf8") as c: master_deck_list = json.loads(c.read()) def get_available_decks(master_deck_list, deck_type_selection): # Assign the list of deck names to deck_list decks_list = [] for av_deck in master_deck_list: if deck_type_selection == 'official': if av_deck['official'] == True: decks_list.append(av_deck['name']) elif deck_type_selection == 'community': if av_deck['official'] == False: decks_list.append(av_deck['name']) elif deck_type_selection == 'all': decks_list.append(av_deck['name']) return decks_list decklist = get_available_decks(master_deck_list, deck_type_selection="official") list_items = tk.StringVar(value=decklist) def update_decklist(list_items): for item in list_items: listbox.insert(tk.END, item) ... # Deck type radio buttons radio_1 = tk.Radiobutton(decktypes_frame, text="Official", variable=deck_type_selection, value="official", command=lambda: update_decklist(list_items)) radio_1.grid(column=0, row=0, padx=5, pady=5) radio_2 = tk.Radiobutton(decktypes_frame, text="Community", variable=deck_type_selection, value="community", command=lambda: update_decklist(list_items)) radio_2.grid(column=1, row=0, padx=5, pady=5) radio_3 = tk.Radiobutton(decktypes_frame, text="All", variable=deck_type_selection, value="all", command=lambda: update_decklist(list_items)) radio_3.grid(column=2, row=0, padx=5, pady=5) # decksframe holds the available and selected decks lists decksframe = tk.LabelFrame(main, text="Available Decks") decksframe.columnconfigure(0, weight=3) decksframe.columnconfigure(1, weight=3) # Available Decks listbox = tk.Listbox(decksframe, selectmode="multiple", listvariable=list_items, exportselection=0) listbox.grid(column=0, row=0, padx=5, pady=5)
完整回溯信息
Exception in Tkinter callback Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.8_3.8.2800.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1892, in __call__ return self.func(*args) File "setup.py", line 63, in <lambda> radio_2 = tk.Radiobutton(decktypes_frame, text="Community", variable=deck_type_selection, value="community", command=lambda: update_decklist(list_items)) File "setup.py", line 40, in update_decklist for item in list_items: TypeError: 'StringVar' object is not iterable
修复步骤
1. 修正get_available_decks的返回逻辑
原函数中return decks_list缩进在for循环内部,导致仅返回第一个符合条件的卡组。将return移到循环外:
def get_available_decks(master_deck_list, deck_type_selection): decks_list = [] for av_deck in master_deck_list: if deck_type_selection == 'official': if av_deck['official'] == True: decks_list.append(av_deck['name']) elif deck_type_selection == 'community': if av_deck['official'] == False: decks_list.append(av_deck['name']) elif deck_type_selection == 'all': decks_list.append(av_deck['name']) # 移到循环外,确保遍历所有卡组后返回完整列表 return decks_list
2. 重写update_decklist函数
原函数错误地遍历StringVar对象,正确逻辑应为获取当前选中类型、重新获取卡组列表、更新ListBox:
def update_decklist(): # 获取单选按钮选中的卡组类型 selected_type = deck_type_selection.get() # 获取对应卡组列表 new_decks = get_available_decks(master_deck_list, selected_type) # 清空ListBox原有内容 listbox.delete(0, tk.END) # 插入新卡组列表 for item in new_decks: listbox.insert(tk.END, item) # 同步更新StringVar,保持与ListBox数据一致 list_items.set(new_decks)
3. 修正单选按钮的command参数
不需要传递list_items,直接绑定update_decklist函数:
radio_1 = tk.Radiobutton(decktypes_frame, text="Official", variable=deck_type_selection, value="official", command=update_decklist) radio_1.grid(column=0, row=0, padx=5, pady=5) radio_2 = tk.Radiobutton(decktypes_frame, text="Community", variable=deck_type_selection, value="community", command=update_decklist) radio_2.grid(column=1, row=0, padx=5, pady=5) radio_3 = tk.Radiobutton(decktypes_frame, text="All", variable=deck_type_selection, value="all", command=update_decklist) radio_3.grid(column=2, row=0, padx=5, pady=5)
效果验证
修复后:
- 窗口加载时会显示所有官方卡组名称
- 点击不同单选按钮,ListBox会实时更新对应类型的卡组列表
- 不再出现
TypeError报错
内容的提问来源于stack exchange,提问作者Sabresong
相关产品推荐
相关产品推荐

