Kivy,重用切换按钮布局,但为按钮分配不同的功能
Kivy, reusing a toggle button layout, but assigning different functions to the buttons
我创建了一个我想重复使用多次的自定义切换按钮布局。我想重用它,因为它包含大量格式。我正在使用生成的 uuid 来分配组,以便多个实例不会相互干扰。
这是我的 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')
这是我的 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()
我希望能够创建 ExampleToggle 小部件的多个副本并为按钮分配不同的功能。我没有问题将函数分配给各个按钮的 on_release 事件,但是如果我这样做,那么对于这个小部件的每个实例来说都是相同的事件。我希望每次重复使用小部件时都能分配不同的功能。
我觉得我要么错过了一些非常简单的东西,要么我走错了路。我尝试了多种不同的方法,并花了很多时间阅读和研究...任何帮助将不胜感激。
您只需要提供一种在运行时设置您调用的函数的方法。
例如,您可以在 ExampleToggle
Python 代码中包含 f1 = ObjectProperty()
和 f2 = ObjectProperty()
,然后在您的 kv 代码中包含 on_release: root.f1()
等。要设置函数,请在 kv 中使用 f1: do_something_a
,或在 python 中使用 your_exampletoggle.f1 = do_something_a
,其中 do_something_a
是一个函数。
经过长时间的休息后,我回到了这里并找出了答案。这是我为其他好奇的人或将来为我自己准备的工作解决方案。我必须在 python 中构建切换布局,然后在 .kv 文件中使用它。关键是使用 'self.dispatch()' 方法。我通过阅读按钮的 kivy 源代码发现了这一点。
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()
我创建了一个我想重复使用多次的自定义切换按钮布局。我想重用它,因为它包含大量格式。我正在使用生成的 uuid 来分配组,以便多个实例不会相互干扰。
这是我的 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')
这是我的 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()
我希望能够创建 ExampleToggle 小部件的多个副本并为按钮分配不同的功能。我没有问题将函数分配给各个按钮的 on_release 事件,但是如果我这样做,那么对于这个小部件的每个实例来说都是相同的事件。我希望每次重复使用小部件时都能分配不同的功能。
我觉得我要么错过了一些非常简单的东西,要么我走错了路。我尝试了多种不同的方法,并花了很多时间阅读和研究...任何帮助将不胜感激。
您只需要提供一种在运行时设置您调用的函数的方法。
例如,您可以在 ExampleToggle
Python 代码中包含 f1 = ObjectProperty()
和 f2 = ObjectProperty()
,然后在您的 kv 代码中包含 on_release: root.f1()
等。要设置函数,请在 kv 中使用 f1: do_something_a
,或在 python 中使用 your_exampletoggle.f1 = do_something_a
,其中 do_something_a
是一个函数。
经过长时间的休息后,我回到了这里并找出了答案。这是我为其他好奇的人或将来为我自己准备的工作解决方案。我必须在 python 中构建切换布局,然后在 .kv 文件中使用它。关键是使用 'self.dispatch()' 方法。我通过阅读按钮的 kivy 源代码发现了这一点。
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()