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

Python Kivy:循环创建按钮后如何正确记录点击的按钮实例?

解决Kivy循环创建按钮时self.i值无法保留的问题

这个问题我太熟了!你遇到的是Python里闭包延迟绑定的经典坑——循环里的self.i在按钮点击触发add方法时才会被读取,这时候循环早就跑完了,self.i自然停在最后一个值(也就是2)。咱们一步步来解决,顺便回答你关于条件判断存储的疑问:

一、最简洁有效的解决方案:直接从按钮实例获取信息

绑定的add方法里的第一个参数(你写的_)其实就是被点击的按钮对象本身!完全不需要依赖self.i,直接从这个参数里拿id或自定义属性就行:

修改你的代码如下:

class InfoPage(GridLayout):
    def __init__(self, **kwargs):
        super(InfoPage, self).__init__(**kwargs)
        self.cols = 1
        self.peers = ["ishika", "nate", "nf"]
        # 建议不要修改原peers列表,直接创建按钮变量
        for i in range(3):
            btn = Button(text=self.peers[i], id=str(i))
            self.add_widget(btn)
            btn.bind(on_press=self.add)
    
    def add(self, button):
        # 直接从点击的按钮实例取id
        id_of_button_pressed = button.id
        print(f"被点击的按钮ID:{id_of_button_pressed}")

这样不管循环怎么运行,每个按钮点击时都会把自己的实例传递给add方法,直接取自己的id,完美规避self.i的问题。

二、如果一定要保留self.i的关联:用默认参数捕获当前值

如果业务逻辑需要用到循环时的i值,可以在绑定事件时用lambda的默认参数,把当前循环的i值固定住(默认参数会在lambda定义时就存储当前值,而不是调用时再读取):

class InfoPage(GridLayout):
    def __init__(self, **kwargs):
        super(InfoPage, self).__init__(**kwargs)
        self.cols = 1
        self.peers = ["ishika", "nate", "nf"]
        for i in range(3):
            btn = Button(text=self.peers[i], id=str(i))
            self.add_widget(btn)
            # 用默认参数current_i=i捕获当前循环的i值
            btn.bind(on_press=lambda _, current_i=i: self.add(_, current_i))
    
    def add(self, _, current_i):
        id_of_button_pressed = self.peers[current_i]
        print(f"当前i值:{current_i},对应按钮文本:{id_of_button_pressed}")

三、关于你问的「用条件判断存储self.i」

其实没必要额外加条件判断——因为on_press事件本身就是只有按钮被点击时才会触发的。不过如果想显式存储每个按钮对应的i值,可以给按钮添加自定义属性:

class InfoPage(GridLayout):
    def __init__(self, **kwargs):
        super(InfoPage, self).__init__(**kwargs)
        self.cols = 1
        self.peers = ["ishika", "nate", "nf"]
        self.stored_i = None  # 用于存储点击的i值
        for i in range(3):
            btn = Button(text=self.peers[i], id=str(i))
            btn.current_i = i  # 给按钮加自定义属性,存当前循环的i
            self.add_widget(btn)
            btn.bind(on_press=self.add)
    
    def add(self, button):
        # 点击时把对应i值存到self.stored_i
        self.stored_i = button.current_i
        print(f"存储的i值:{self.stored_i},按钮ID:{button.id}")

这样就实现了“点击按钮时将对应i值存储到其他变量”的需求。

内容的提问来源于stack exchange,提问作者ishika

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:02:30