Kivy中Popup绑定带参数函数崩溃,寻求修复方案
Kivy Popup按钮绑定报错修复方案
问题描述
点击动物选择器的PinButton后,弹出确认Popup,但绑定Yes按钮到pin_it函数时触发报错:
File "/home/sib/PycharmProjects/SpotMap/animalWindow.py", line 66, in pin_action yes_btn.bind(on_press=pin_it(_animal)) File "kivy/_event.pyx", line 444, in kivy._event.EventDispatcher.bind AssertionError: None is not callable
单独执行pin_it(_animal)能正常打印,但放到bind逻辑里就崩溃。
错误原因
yes_btn.bind(on_press=pin_it(_animal))这行代码里,pin_it(_animal)是直接调用函数,执行后返回None(因为pin_it没有return语句),而Kivy的bind方法需要传入一个可调用的函数对象,不是函数执行后的结果,因此触发"None is not callable"错误。
修复方案
方法1:使用lambda表达式包装函数
lambda可以把带参数的函数转换成bind能接受的格式,修改绑定代码如下:
yes_btn.bind(on_press=lambda x: pin_it(_animal))
同时补充No按钮的关闭Popup逻辑(原代码遗漏):
no_btn.bind(on_release=popup.dismiss)
方法2:使用functools.partial(更清晰的参数传递)
先导入工具类:
from functools import partial
再修改绑定代码:
yes_btn.bind(on_press=partial(pin_it, _animal))
修正后的完整pin_action函数
# 若用方法2,需添加这行导入 from functools import partial class ANIMALPICKER(RelativeLayout): def pin_action(self, _animal): # Prepare to confirm that you want to Pin the sighting title_text = _animal + ' ' + 'SIGHTING' content_text = 'Confirm Sighting?' content_box = BoxLayout(orientation='vertical') btn_box = BoxLayout(orientation='horizontal') btn_box.height = 24 content_label = Label() content_label.text = content_text yes_btn = Button(text='Yes') yes_btn.background_color = 0, 1, 0, 1 no_btn = Button(text='No') no_btn.background_color = 1, 0, 0, 1 btn_box.add_widget(yes_btn) btn_box.add_widget(no_btn) content_box.add_widget(content_label) content_box.add_widget(btn_box) # Now confirm that you want to Pin the sighting popup = Popup(title=title_text, separator_height=4, title_size='20sp', content=content_box, size_hint=(None, None), size=(200, 240), auto_dismiss=False) # 二选一:方法1用lambda绑定 yes_btn.bind(on_press=lambda x: pin_it(_animal)) # 二选一:方法2用partial绑定(需先导入functools.partial) # yes_btn.bind(on_press=partial(pin_it, _animal)) yes_btn.bind(on_release=popup.dismiss) # 给No按钮绑定关闭Popup逻辑 no_btn.bind(on_release=popup.dismiss) popup.open()
补充说明
- lambda里的
x是Kivy按钮事件默认传递的参数(按钮实例本身),必须写上,否则会触发参数不匹配错误。 partial会预先把_animal传给pin_it函数,按钮触发时会自动带上该参数,逻辑更直观。
内容的提问来源于stack exchange,提问作者Sib Andela
相关产品推荐
相关产品推荐

