Mentions a problem with Kivy’s get_property_observers() where method_name cannot be retrieved when a callback function with arguments is bound.
get_property_observers()
The get_property_observers() is a method that returns a list of callback functions bound to a property or event, allowing the bound callback functions to be examined.
See below for details and sample code of the get_property_observers() method.
Specifying args = True as a parameter to this method returns a list similar to the following.
[<WeakMethod proxy=<__main__.RootWidget object at 0x00000164BC361240> method=None method_name=on_callback>]
The method_name contains the callback function name. This is the list of callback functions when bound with no arguments. I am making a note of this because I have encountered a phenomenon where method_name is None or the element does not exist in the case of a callback function with arguments.
Phenomenon that method_name cannot be obtained
In the case of a callback function with arguments, method_name could not be obtained. I don’t know if it is related to weak references, a bug, or my fault, but I couldn’t solve this problem. I would appreciate comments from anyone who can help me understand this phenomenon.
When using bind()
# For bind With argument
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from functools import partial
from kivy.lang import Builder
kv_code = Builder.load_string('''
<RootWidget>:
orientation: 'vertical'
Button:
id: button2
text: "Unbind Callback"
font_size: 30
on_press: root.unbind_callback()
''')
class RootWidget(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.register_event_type('on_custom_event')
self.bind(on_custom_event=partial(self.on_callback,'args1','args2',kwargs='kwargs'))
# Custon Event1
def on_custom_event(self,*args):
print('on_custom_event was called')
# Callback
def on_callback(self, *args, **kwargs):
print('on_callback has been called')
# Unbind callback functions.
def unbind_callback(self):
print(self.get_property_observers('on_custom_event', args = True))
#self.funbind('on_custom_event',self.on_callback,'args1','args2',kwargs='kwargs')
class KivyEventsCustomEvent3(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
KivyEventsCustomEvent3().run()
If I specify arguments to the callback function in bind(), method_name=None. And the argument is not in the element where it should fit. It should be correct that args should be in index 2 and kwargs in index 3.
# For bind With argument.
[(<WeakMethod proxy=None method=functools.partial(<bound method RootWidget.on_callback of <__main__.RootWidget object at 0x00000264A5C87D90>>, 'args1', 'args2', kwargs='kwargs') method_name=None>, (), {}, 1, None)]
Using fbind()
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
kv_code = Builder.load_string('''
<RootWidget>:
orientation: 'vertical'
Button:
id: button2
text: "Unbind Callback"
font_size: 30
on_press: root.unbind_callback()
''')
class RootWidget(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.register_event_type('on_custom_event')
self.fbind('on_custom_event',self.on_callback,'args1','args2',kwargs='kwargs')
# Custon Event1
def on_custom_event(self,*args):
print('on_custom_event was called')
# Callback
def on_callback(self, *args, **kwargs):
print('on_callback has been called')
# Unbind callback functions.
def unbind_callback(self):
print(self.get_property_observers('on_custom_event', args = True))
#self.funbind('on_custom_event',self.on_callback,'args1','args2',kwargs='kwargs')
class KivyEventsCustomEvent3(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
KivyEventsCustomEvent3().run()
If we use fbind(), method_name has disappeared. However, the arguments are in elements that should fit. It is correct that args is in index 2 and kwargs is in index 3.
# For fbind With argument.
[(<bound method RootWidget.on_callback of <__main__.RootWidget object at 0x00000262DA867D90>>, ('args1', 'args2'), {'kwargs': 'kwargs'}, 0, 1)]
Comment