为什么在 Kivy 中无法通过回调触发事件

Why it's not possible to trigger an event from callback in Kivy

大家好!

我 运行 遇到 Kivy + 事件和回调 的问题。

当我尝试 运行 来自另一个回调的回调时 - 它失败了。

第一个回调 on_spinner1_select 应该用 ClockEvent self._myevent = Clock.create_trigger(...) 触发第二个回调 _update_something。第一个回调被正确调用,但 _update_something 永远不会被调用。 这种行为的原因是什么?

这是我的简单示例:

import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
import time


kv_app_layout = """
#<KvLang>
MyLayout:
    id: _mylayout
    spinner1: _spnr1
    label1: _lbl1
    orientation: 'vertical'
    padding: 2
    spacing: 2
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Line:
            width: .5
            rectangle: (self.x+1, self.y-1, self.width-2, self.height-1)
    Spinner:
        id: _spnr1
        text:  'Some Text'
        values:   ['A', 'B', 'C', 'D']
        size_hint:  1, .5
        on_text:  root.on_spinner1_select(self.text)

    Label:
        id: _lbl1
        size_hint:  1, .5
#</KvLang>
"""


class MyLayout(BoxLayout):
    
    spinner1 = ObjectProperty(None)
    label1 = ObjectProperty(None)

    def __init__(self, **kwargs):
        self._myevent = Clock.create_trigger(lambda dt: self._update_something)
        super().__init__(**kwargs)

    def on_spinner1_select(self, text):
        self._myevent()

    def _update_something(self):
        print(f"Called: {time.asctime()}")
        self.label1.text = f"{self.spinner1.text} called on {time.asctime()}"

class SampleApp(App):
    def build(self):
        return Builder.load_string(kv_app_layout)


if __name__ == '__main__':
    SampleApp().run()

我在:

通过稍微修改您的代码,我设法调用了 _update_something

Here's the result of the code

import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
import time


kv_app_layout = """
#<KvLang>
MyLayout:
    id: _mylayout
    spinner1: _spnr1
    label1: _lbl1
    orientation: 'vertical'
    padding: 2
    spacing: 2
    canvas.before:
        Color:
            rgba: 1, 1, 1, 1
        Line:
            width: .5
            rectangle: (self.x+1, self.y-1, self.width-2, self.height-1)
    Spinner:
        id: _spnr1
        text:  'Some Text'
        values:   ['A', 'B', 'C', 'D']
        size_hint:  1, .5
        on_text:  root.on_spinner1_select(self.text)

    Label:
        id: _lbl1
        size_hint:  1, .5
#</KvLang>
"""


class MyLayout(BoxLayout):

    spinner1 = ObjectProperty(None)
    label1 = ObjectProperty(None)

    def __init__(self, **kwargs):
        self._myevent = Clock.create_trigger(self._update_something)
        super().__init__(**kwargs)

    def on_spinner1_select(self, text):
        self._myevent()

    def _update_something(self,dt):
        print(f"Called: {time.asctime()}")
        self.label1.text = f"{self.spinner1.text} called on {time.asctime()}"

class SampleApp(App):
    def build(self):
        return Builder.load_string(kv_app_layout)


if __name__ == '__main__':
    SampleApp().run()

确保遵循 Kivy Documentation

中规定的格式

使用 lambda 函数应该也可以,但我不确定。