I have created a custom toggle button layout that I would like to reuse multiple times. I would like to reuse it as it contains extensive formatting. I am using generated uuid's to assign the groups so that the multiple instances don't interfere with each other.
Here my test.kv:
#:kivy 2.0.0
#:import uuid uuid
<ExampleToggle@BoxLayout>:
uuid: uuid.uuid4()
orientation: 'horizontal'
ToggleButton:
id: run
text: 'RUN'
group: root.uuid
on_release: root.on_run()
ToggleButton:
id: stop
text: 'STOP'
group: root.uuid
on_release: root.on_stop()
<TestDisplay>:
BoxLayout:
orientation: 'vertical'
ExampleToggle:
on_run: print('A')
on_stop: print('B')
ExampleToggle:
on_run: print('C')
on_stop: print('D')
Here is my test.py:
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.widget import Widget
class ExampleToggle():
on_run = ObjectProperty(None)
on_stop = ObjectProperty(None)
def on_run(self, *args):
# Dummy function
pass
def on_stop(self, *args):
# Dummy function
pass
class TestDisplay(Widget):
pass
class TestApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return TestDisplay()
if __name__ == '__main__':
TestApp().run()
I would like to be able to create multiple copies of the ExampleToggle widget and assign different functions to the buttons. I have no issue assigning a function to the on_release event of the individual buttons, however if I do that then it is the same event for every instance of this widget. I would like to be able to assign different functions every time I reuse the widget.
I feel I am either missing something ridiculously simple, or I am going down the wrong path. I have tried multiple different methods, and spent a ton of time reading and researching... Any help would be greatly appreciated.
After a long break I came back to this and worked out the answer. Here is my working solution for others who are curious, or for myself in the future. I had to build the toggle layout in python and then use it in the .kv file. The key was using the 'self.dispatch()' method. I found this from reading through the kivy source code for buttons.
test.kv:
#:kivy 2.0.0
#:import uuid uuid
#:import ExampleToggle test
<TestDisplay>:
BoxLayout:
orientation: 'vertical'
ExampleToggle:
on_run: print('A')
on_stop: print('B')
ExampleToggle:
on_run: print('C')
on_stop: print('D')
test.py:
from uuid import uuid4
import kivy
kivy.require('2.0.0')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.boxlayout import BoxLayout
class ExampleToggle(BoxLayout):
def __init__(self, **kwargs):
self.register_event_type('on_run')
self.register_event_type('on_stop')
super(ExampleToggle, self).__init__(**kwargs)
self.groupid = uuid4()
self.orientation = 'horizontal'
self.size_hint = (None, .1)
self.width: self.height * 5
self.state = None
rbtn = ToggleButton(text='RUN',
group=self.groupid,
allow_no_selection=False)
sbtn = ToggleButton(text='STOP',
group=self.groupid,
allow_no_selection=False)
self.add_widget(rbtn)
self.add_widget(sbtn)
rbtn.bind(on_release=self.run)
sbtn.bind(on_release=self.stop)
def run(self, *args):
if self.state != 'RUN':
self.dispatch('on_run')
self.state = 'RUN'
def stop(self, *args):
if self.state != 'STOP':
self.dispatch('on_stop')
self.state = 'STOP'
def on_run(self):
pass
def on_stop(self):
pass
class TestDisplay(Widget):
pass
class TestApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return TestDisplay()
if __name__ == '__main__':
TestApp().run()