我正在构建一款流行派对游戏的 Python 版本,并且我正在使用 tkinter 构建带有玩家名称和游戏首选项的设置 GUI。当我运行代码时,窗口会打开,除了一件关键的事情外,它看起来很正确。
有单选按钮可以选择牌组类型,还有一个列表框用于显示游戏中牌组的名称,只要单击单选按钮,该列表框就会更新。
获取套牌名称列表在命令行上工作正常,但我无法使其在 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
错误消息的含义与它所说的完全一样。
list_items
不是一个列表,也不是一个字符串,它是一个 StringVar
。你不能这样做 for item in list_items
因为 list_items
不支持迭代。
解决方案似乎是简单地将
list_items
设置为 decklist
(或者直接扔掉 list_items
并直接使用 decklist
)。然后,只需将项目插入列表框中,而不是使用 listvariable
。例如:
listbox = tk.Listbox(decksframe, selectmode="multiple", exportselection=0)
listbox.insert("end", *decklist)