如何遍历Combobox并设置值?代码报错“'str' object has no attribute 'set'”
你遇到的问题核心很明确——你生成的combo是一个字符串(比如"combobox_001"),但set()是Combobox组件对象的专属方法,字符串类型当然没有这个方法,所以才会触发报错。
要解决这个问题,我们需要直接操作Combobox的实例对象,而不是它们的名字字符串。这里给你推荐几种靠谱的方案,其中第一种最适合你有153个组件的场景:
方案1:提前维护Combobox对象字典(最推荐)
在创建每个Combobox的时候,把它们存入一个以ID为键的字典中,这样后续循环时可以直接通过ID快速找到对应的组件对象。
步骤1:创建并维护Combobox字典
在你的主代码部分,先定义一个全局字典(如果是类结构的话可以用类属性),然后在创建每个Combobox时将其加入字典:
# 定义全局字典存储Combobox对象,键为对应的ID(如"001") combobox_dict = {} # 主代码中创建Combobox_001的部分修改如下 values_001 = list(range(20, 4020, 20)) combobox_001 = ttk.Combobox(main_frame, width=15, values=values_001) combobox_001.set("300 msec") combobox_001.state(["readonly"]) combobox_001.grid(row=0, column=1, padx=5, pady=5, sticky="w") # 将对象存入字典,键为"001" combobox_dict["001"] = combobox_001 # 同理处理Combobox_002 values_002 = list(range(20, 4020, 20)) combobox_002 = ttk.Combobox(main_frame, width=15, values=values_002) combobox_002.set("700 msec") combobox_002.state(["readonly"]) combobox_002.grid(row=1, column=1, padx=5, pady=5, sticky="w") combobox_dict["002"] = combobox_002
步骤2:修改new_file函数使用字典
在new_file中,直接通过ID从字典取对象并调用set方法:
def new_file(): global combobox_dict # 引用全局字典 file_path = 'Default_Menu_Values.991A' data = load_json_file(file_path) try: # 遍历需要设置的ID范围,或者直接遍历data的键更灵活 for m in range(1, 3): # 示例为1-2,实际可改为1到154 ID = f"{m:03}" # 检查ID是否同时存在于数据和字典中 if ID in data and ID in combobox_dict: menu_value = str(data[ID]) # 直接操作Combobox对象 combobox_dict[ID].set(menu_value) except Exception as e: print(f"An error occurred: {e}")
这个方案的优势是代码清晰、查找效率高,而且后续维护组件也很方便,完全避免了字符串和对象混淆的问题。
方案2:通过父组件遍历子组件(适合不想维护字典的场景)
如果不想单独维护字典,可以通过Combobox的父容器(比如main_frame)遍历所有子组件,筛选出Combobox类型且符合命名规则的对象。
需要注意的是,默认情况下ttk.Combobox的winfo_name()不是你定义的变量名,所以需要在创建时手动指定name参数:
# 创建Combobox时手动设置name属性 combobox_001 = ttk.Combobox(main_frame, width=15, values=values_001, name="combobox_001") combobox_002 = ttk.Combobox(main_frame, width=15, values=values_002, name="combobox_002")
然后修改new_file函数:
def new_file(): file_path = 'Default_Menu_Values.991A' data = load_json_file(file_path) try: # 遍历main_frame的所有子组件 for widget in main_frame.winfo_children(): # 筛选出Combobox且name符合combobox_XXX格式的组件 if isinstance(widget, ttk.Combobox) and widget.winfo_name().startswith("combobox_"): # 提取ID部分(从"combobox_001"中得到"001") id_str = widget.winfo_name().split("_")[-1] if id_str in data: menu_value = str(data[id_str]) widget.set(menu_value) except Exception as e: print(f"An error occurred: {e}")
方案3:通过globals()获取对象(不推荐)
你可以通过Python的globals()字典直接根据变量名字符串获取对象,但这种方式耦合性高,不利于代码维护(尤其是组件数量多的时候),仅作了解:
def new_file(): file_path = 'Default_Menu_Values.991A' data = load_json_file(file_path) try: for m in range(1, 3): ID = f"{m:03}" Menu_Value = str(data.get(ID)) # 通过globals()根据字符串获取Combobox对象 combo = globals()[f"combobox_{ID}"] combo.set(Menu_Value) except Exception as e: print(f"An error occurred: {e}")
这个方法虽然能解决问题,但如果后续变量名修改、或者组件不是全局变量时会出错,所以不推荐在生产代码中使用。
备注:内容来源于stack exchange,提问作者user29962476

