Reputation: 169
I am writing a program that has a panel of buttons on the right hand side, that successfully binds a method to each, dependant on user input/actions. My issues is that I cannot unbind()
the method explicitely, as the method bound is dynamic.
Consider;
i = 1
while i <= 8:
string = "action" + str(i)
#Buttons named 'action1, action1, ..., action8'
ref = self.ids[string]
ref.text = ""
observers = ref.get_property_observers('on_release')
print observers
ref.unbind()
ref.bind(on_release=partial(self.BlankMethod, arg1))
i += 1
The lines;
observers = ref.get_property_observers('on_release')
print observers
Show that I have an increasing list of weakmethods bound, every time the method is called, but the unbind function does not unbind the method.
Although my code example does not show it, the bound method changes regularly, and the self.BlankMethod
was meant to override the original binding. This is not the case, and the Button
's bound methods increase.
[<kivy.weakmethod.WeakMethod object at 0x7f8cc826a810>]
[<kivy.weakmethod.WeakMethod object at 0x7f8cc826a850>, <kivy.weakmethod.WeakMethod object at 0x7f8cc826acd0>]
I have tried;
observers = ref.get_property_observers('on_release')
if observers != []:
for observer in observers:
ref.unbind(observer)
ref.bind(on_release=partial(self.Blank))
But I am returned the error;
TypeError: unbind() takes exactly 0 positional arguments (1 given)
I had a look at using funbind()
function but subsequently given;
AttributeError: 'Button' object has no attribute 'funbind'
Trying to use fbind()
prior to funbind()
also gives the same error, but with respect to the button not having an fbind()
attribute.
How can I list all bound methods of an object, and subsequently unbind them?
Upvotes: 3
Views: 2672
Reputation: 5157
Here is a toy example demonstrating setting, saving, and later clearing callbacks. When a_button
or b_button
is pressed, set_callbacks
is triggered, which binds callbacks to all of MyButton
s. MyButton
has a list property _cb
storing user defined callbacks. c_button
will trigger clear_callbacks
, which goes through each of the MyButton
's _cb
lists and unbinds each stored callback.
from kivy.app import App
from kivy.lang import Builder
from functools import partial
kv_str = """
<MyButton@Button>:
_cb: []
my_id: 1
text: "hello {}".format(self.my_id)
BoxLayout:
orientation: 'vertical'
BoxLayout:
Button:
id: a_button
text: "a button"
Button:
id: b_button
text: "b button"
Button:
id: c_button
text: "clear callbacks"
GridLayout:
cols: 4
id: grid
MyButton:
my_id: 1
MyButton:
my_id: 2
MyButton:
my_id: 3
MyButton:
my_id: 4
"""
def cb(sender, arg='nothing'):
print "we got: {} pressed with {}".format(sender.text, arg)
class MyApp(App):
def build(self):
root = Builder.load_string(kv_str)
def set_callbacks(sender):
for b in root.ids.grid.children:
new_cb = partial(cb, arg=sender.text)
b._cb.append(new_cb)
b.fbind('on_press', new_cb)
def clear_callbacks(sender):
for b in root.ids.grid.children:
for cb in b._cb:
b.funbind('on_press', cb)
b._cb = []
root.ids.a_button.bind(on_press=set_callbacks)
root.ids.b_button.bind(on_press=set_callbacks)
root.ids.c_button.bind(on_press=clear_callbacks)
return root
if __name__ == '__main__':
a = MyApp()
a.run()
Upvotes: 3