You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

解决方案

问题根源分析

  1. Value after * must be an iterable, not PackingList报错:你在show_frame(OpenList, *objectID)中使用*解包,但objectID是单个PackingList对象,并非列表、元组这类可迭代类型,因此触发报错。
  2. 传递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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:35:21