Python/Tkinter中对象跨Frame传递失败的问题求助
问题描述
我尝试通过Frame类的方法将PackingList实例化对象传递给新Frame,参考类似方案后报错:Value after * must be an iterable, not PackingList。改为传递对象的name属性后,目标Frame仅收到空元组,目前无法推进,寻求技术解决。相关代码如下:
App类代码
class App(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) container = tk.Frame(self) container.pack(side = "top", fill = "both", expand = True) container.grid_rowconfigure(0, weight = 1) container.grid_columnconfigure(0, weight = 1) self.frames = {} for F in (Homescreen, Menuscreen, Create, ShowUpcoming, ShowAll, OpenList, Search, Edit): frame = F(container, self, *args, **kwargs) self.frames[F] = frame frame.grid(row = 0, column = 0, sticky = "nsew") self.show_frame(Homescreen) def show_frame(self, container, *args, **kwargs): frame = self.frames[container] frame.tkraise()
ShowAll类代码
class ShowAll(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) tk.Label(self, text = "Alla packningslistor", font = ("Times new roman", 30)).place(x = 110, y = 0) self.controller = controller objectList = PK.main() objectOpen = PK.showAll(objectList) self.radiobutton_list = [] self.objectList = objectList for i in range(len(objectOpen)): radiobutton = tk.Radiobutton(self, text = objectOpen[i], command = functools.partial(self.objectToOpen, idx = i)).place(x = 150, y = 100 + i*30) self.radiobutton_list.append(radiobutton) def objectToOpen(self, idx): objectID = self.objectList[idx] return self.controller.show_frame(OpenList, *objectID)
OpenList类代码
class OpenList(tk.Frame): def __init__(self, parent, controller, *objectID): tk.Frame.__init__(self, parent) #lala = getattr(objectID, "name") #print(lala)
解决方案
问题根源分析
Value after * must be an iterable, not PackingList报错:你在show_frame(OpenList, *objectID)中使用*解包,但objectID是单个PackingList对象,并非列表、元组这类可迭代类型,因此触发报错。- 传递name属性收到空元组:所有Frame在App初始化时已创建完成,
OpenList的__init__仅执行一次,且App初始化时未传入任何参数,导致*objectID为空元组;后续调用show_frame传递的参数未被处理,根本没传到OpenList中。
具体修改步骤
1. 改造App类的show_frame方法,支持传递参数给目标Frame
原方法仅负责切换Frame,需新增参数传递逻辑,调用目标Frame的更新方法:
def show_frame(self, container, *args, **kwargs): frame = self.frames[container] # 若目标Frame有update_data方法,调用它传递参数 if hasattr(frame, 'update_data'): frame.update_data(*args, **kwargs) frame.tkraise()
2. 修正ShowAll类的objectToOpen方法,正确传递参数
无需对单个对象使用*解包,直接传递即可:
def objectToOpen(self, idx): objectID = self.objectList[idx] # 传递完整PackingList对象 return self.controller.show_frame(OpenList, objectID) # 若仅需传递name属性,改为: # return self.controller.show_frame(OpenList, objectID.name)
3. 给OpenList类添加update_data方法,接收并处理参数
由于__init__仅执行一次,需新增方法来接收切换Frame时传递的参数:
class OpenList(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller # 初始化显示控件,比如用于展示name的标签 self.name_label = tk.Label(self, text="", font=("Times new roman", 20)) self.name_label.place(x=100, y=100) def update_data(self, data): # 处理传递过来的PackingList对象或name属性 if isinstance(data, PackingList): self.name_label.config(text=f"列表名称:{data.name}") # 这里可以添加更多对象属性的展示逻辑 else: self.name_label.config(text=f"列表名称:{data}")
内容的提问来源于stack exchange,提问作者MoniqueAshkenaz
相关产品推荐
相关产品推荐

