假设我的 Test.kv 编写如下:
#:kivy 2.0.0
<Test>:
Label:
id: inner_label_top
text: root.name
<Root>:
Test:
id: test_1
Test:
id: test_2
在python上:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
class Root(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
class Test(BoxLayout):
def __init__(self, name, **kwargs):
self.name = name
super().__init__(**kwargs)
class TestApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
return Root()
# return Root(self.send_channel) # <<---
if __name__ == '__main__':
TestApp().run()
# trio.run(TestApp().app_func)
在这种情况下, Root 小部件实例化2个 Test 小部件,但是 Test 小部件需要__init__
的参数。
但是,我找不到方法 Root 将参数传递给子窗口小部件,因为它们是在 .kv 文件中实例化的,而我对此无能为力-至少对于我在不完整的2.0.0 rc4文档中所看到的内容。
没有global
范围,有什么方法可以传递参数?
每个小部件的实际实现都实现了async
方法。
具有以下trio
和kivy
样板:
class InnerWidgetApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.nursery = None
self.send_channel, self.recv_channel = trio.open_memory_channel(512)
def build(self):
return InnerWidget('some nice name', self.send_channel)
async def app_func(self):
async with trio.open_nursery() as nursery:
self.nursery = nursery
async def wrapper():
await self.async_run('trio')
nursery.cancel_scope.cancel()
nursery.start_soon(wrapper)
nursery.start_soon(self.wait_for_tasks)
async def wait_for_tasks(self):
async for task in self.recv_channel:
print(f"Task recv: {task} Type {type(task)}")
self.nursery.start_soon(task)
App自行计划的地方,然后开始通过async
接收trio.MemoryReceiveChannel
方法并计划nursery
中的方法。
因此,子窗口小部件应在trio.MemorySendChannel
上收到__init__
,这在未嵌套窗口小部件时效果很好。
以下是实际小部件的抽象定义:
class InnerWidget(ButtonBehavior, BoxLayout):
...
def __init__(self, name, task_queue: trio.MemorySendChannel, **kwargs):
self.task_send_ch = task_queue
super().__init__(**kwargs)
async def update(self):
...
def on_press(self):
self.task_send_ch.send_nowait(self.update)
但是,由于该小部件打算被多次实例化-可能大约100次-我别无选择,只能将它们放在其他小部件中并在其中放置一些控制界面。