从外部将函数绑定到自定义小部件内的按钮
Binding function to a button inside a Custom Widget from outside
我制作了这个小部件:
<ImageButton>:
source:''
text:''
release_fn: None
Button:
on_release: root.release_fn()
size: root.size
pos: root.pos
BoxLayout:
padding: 30
size: self.parent.size
pos: self.parent.pos
orientation:'vertical'
Image:
id: img
source: root.source
Label:
size_hint_y:.3
text: root.text
现在我想传递给它一个函数,在释放按钮时调用它,但我不知道该怎么做(而且我找不到任何答案...)
以下仅在最后一行给我一个语法错误(省略了 kivy 文件的其余部分和良好的工作部分)
ImageButton:
source: 'iconUsuario.png'
text: 'Usuario'
release_fn: print('HI!')
print('HI!')
^
SyntaxError: invalid syntax
Python 出于某种原因不喜欢将其印刷品用作其他任何东西的名称。尝试 运行 这个:
def print():
pass
def print:
pass
总是 SyntaxError
在 print。 KV lang 基本上是这样做的:
eval(print('bla'))
所以,让我们为打印件包装一个。无论如何,您可能不会使用纯打印。然后你可能会注意到函数 returns None
,那是因为它是用 on_release: root.release_fn()
调用的,因为第一个值 release_fn: something()
就像一个部分(当你调用 partial(func, arg)()
函数真的被调用了)。
这就是为什么您需要导入 functools.partial
,再做一次,以便在按下按钮后在所需位置调用该函数,而不是立即调用:
on_release: root.release_fn()
示例:
from kivy.app import App
from kivy.lang import Builder
kv = """
#:import partial functools.partial
ImageButton:
release_fn: partial(app.prints, 'bla')
<ImageButton@ButtonBehavior+Image>:
source:''
text:''
release_fn: None
Button:
on_release: root.release_fn()
size: root.size
pos: root.pos
BoxLayout:
padding: 30
size: self.parent.size
pos: self.parent.pos
orientation:'vertical'
Image:
id: img
source: root.source
Label:
size_hint_y:.3
text: root.text
"""
class TestApp(App):
def prints(self, value):
print(value)
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
TestApp().run()
好吧,事实证明这似乎不是最好的主意,我使用了自定义事件:
class ImageButton(Widget):
def __init__(self,*args,**kwargs):
super(ImageButton,self).__init__(*args,**kwargs)
self.register_event_type('on_release')
def on_release(self,*args):
pass
def callback(self,instance):
self.dispatch('on_release')
pass
kv 文件:
<ImageButton>:
source:''
text:''
Button:
on_release: root.callback(self)
size: root.size
pos: root.pos
BoxLayout:
padding: 30
size: self.parent.size
pos: self.parent.pos
orientation:'vertical'
Image:
id: img
source: root.source
Label:
size_hint_y:.3
text: root.text
我制作了这个小部件:
<ImageButton>:
source:''
text:''
release_fn: None
Button:
on_release: root.release_fn()
size: root.size
pos: root.pos
BoxLayout:
padding: 30
size: self.parent.size
pos: self.parent.pos
orientation:'vertical'
Image:
id: img
source: root.source
Label:
size_hint_y:.3
text: root.text
现在我想传递给它一个函数,在释放按钮时调用它,但我不知道该怎么做(而且我找不到任何答案...)
以下仅在最后一行给我一个语法错误(省略了 kivy 文件的其余部分和良好的工作部分)
ImageButton:
source: 'iconUsuario.png'
text: 'Usuario'
release_fn: print('HI!')
print('HI!')
^
SyntaxError: invalid syntax
Python 出于某种原因不喜欢将其印刷品用作其他任何东西的名称。尝试 运行 这个:
def print():
pass
def print:
pass
总是 SyntaxError
在 print。 KV lang 基本上是这样做的:
eval(print('bla'))
所以,让我们为打印件包装一个。无论如何,您可能不会使用纯打印。然后你可能会注意到函数 returns None
,那是因为它是用 on_release: root.release_fn()
调用的,因为第一个值 release_fn: something()
就像一个部分(当你调用 partial(func, arg)()
函数真的被调用了)。
这就是为什么您需要导入 functools.partial
,再做一次,以便在按下按钮后在所需位置调用该函数,而不是立即调用:
on_release: root.release_fn()
示例:
from kivy.app import App
from kivy.lang import Builder
kv = """
#:import partial functools.partial
ImageButton:
release_fn: partial(app.prints, 'bla')
<ImageButton@ButtonBehavior+Image>:
source:''
text:''
release_fn: None
Button:
on_release: root.release_fn()
size: root.size
pos: root.pos
BoxLayout:
padding: 30
size: self.parent.size
pos: self.parent.pos
orientation:'vertical'
Image:
id: img
source: root.source
Label:
size_hint_y:.3
text: root.text
"""
class TestApp(App):
def prints(self, value):
print(value)
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
TestApp().run()
好吧,事实证明这似乎不是最好的主意,我使用了自定义事件:
class ImageButton(Widget):
def __init__(self,*args,**kwargs):
super(ImageButton,self).__init__(*args,**kwargs)
self.register_event_type('on_release')
def on_release(self,*args):
pass
def callback(self,instance):
self.dispatch('on_release')
pass
kv 文件:
<ImageButton>:
source:''
text:''
Button:
on_release: root.callback(self)
size: root.size
pos: root.pos
BoxLayout:
padding: 30
size: self.parent.size
pos: self.parent.pos
orientation:'vertical'
Image:
id: img
source: root.source
Label:
size_hint_y:.3
text: root.text