Kivy:如何为回调传递参数并通过自省确定参数?
解决Kivy中bind()绑定可变参数函数无参数传入的问题
问题说明
在Kivy 2.2.0文档第247页的示例中,btn4绑定的on_anything函数被设计为接受可变参数,但运行精简代码后按下按钮,发现*args和**kwargs输出为空;尝试直接给bind()添加参数会报错,需要实现传递参数让print语句输出内容。
解决方案
1. 利用Kivy事件自带的参数
Kivy的on_press事件默认会将触发事件的控件实例作为第一个位置参数传入回调函数。原代码中on_anything的*args本应包含按钮实例,若你运行时输出为空,可检查代码运行环境或确保按钮绑定逻辑正确。以下是验证该逻辑的代码:
from kivy.uix.boxlayout import BoxLayout from kivy.app import App from kivy.uix.button import Button class DemoBox(BoxLayout): def __init__(self, **kwargs): super(DemoBox, self).__init__(**kwargs) self.orientation = "vertical" btn4 = Button(text="Use a flexible function") btn4.bind(on_press=self.on_anything) self.add_widget(btn4) def on_anything(self, *args, **kwargs): print('The flexible function has *args of', str(args), "and **kwargs of", str(kwargs)) # 提取事件传入的按钮实例做操作 if args: print("触发事件的按钮文本:", args[0].text) class DemoApp(App): def build(self): return DemoBox() if __name__ == "__main__": DemoApp().run()
运行后按下按钮,会输出按钮实例对象及文本,证明事件参数已正常传入。
2. 传递自定义额外参数
若需要给回调函数传递自定义参数,不能直接在bind()中添加,需使用functools.partial包装函数,将额外参数绑定到回调中:
from kivy.uix.boxlayout import BoxLayout from kivy.app import App from kivy.uix.button import Button from functools import partial class DemoBox(BoxLayout): def __init__(self, **kwargs): super(DemoBox, self).__init__(**kwargs) self.orientation = "vertical" btn4 = Button(text="Use a flexible function") # 使用partial绑定自定义参数,比如字符串和数字 btn4.bind(on_press=partial(self.on_anything, "自定义参数1", 123)) self.add_widget(btn4) def on_anything(self, custom_arg1, custom_arg2, *args, **kwargs): print('自定义参数:', custom_arg1, custom_arg2) print('事件传入的参数:', str(args)) print('关键字参数:', str(kwargs)) class DemoApp(App): def build(self): return DemoBox() if __name__ == "__main__": DemoApp().run()
此时按下按钮,on_anything会先接收partial绑定的自定义参数,再接收Kivy事件传入的控件实例参数,实现自定义参数传递。
关键说明
- Kivy事件的回调函数签名由事件类型决定:
on_press仅传递控件实例,on_release同理;部分复杂事件(如on_touch_down)会传递更多参数。 - 使用
functools.partial时,自定义参数会被放在事件参数之前,需注意参数顺序。
内容的提问来源于stack exchange,提问作者no-one
相关产品推荐
相关产品推荐

