Kivy 2.0.0rc4带有__init__参数的子窗口小部件

时间:2020-11-08 05:56:11

标签: python kivy

问题Y:

假设我的 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范围,有什么方法可以传递参数?


问题X-上下文:

每个小部件的实际实现都实现了async方法。

具有以下triokivy样板:

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次-我别无选择,只能将它们放在其他小部件中并在其中放置一些控制界面。

0 个答案:

没有答案