【问题标题】:Is it possible to schedule Kivy StringProperty set() method using Clock?是否可以使用 Clock 来安排 Kivy StringProperty set() 方法?
【发布时间】:2019-01-09 12:22:13
【问题描述】:

我想延迟 Kivy 屏幕管理器转换,例如我可以这样做:

#!/usr/bin/env python

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty
from kivy.uix.button import Button
from kivy.clock import Clock

Builder.load_string('''
#: kivy 1.9.2
#: import sm kivy.uix.screenmanager
#: set base_font_size 25

<MainWidget>:
    manager: screen_manager

    ScreenManager:
        id: screen_manager
        transition: sm.NoTransition()
        Screen:
            name: 'screen_one'  
            Button:
                text: 'Screen 1, press to switch to Screen 2'
                font_size: base_font_size
                on_press:
                    root.manager.current = 'screen_two'
                    root.statusmsg = 'Screen 2, press to launch Armageddon'

        Screen:
            name: 'screen_two'
            Button:
                text: root.statusmsg
                font_size: base_font_size
                disabled: True if root.statusmsg == 'Busy launching Armageddon' else False # prevent multiple activation
                on_press:
                    root.deliver_payload()

''')


class MainWidget(FloatLayout):

    statusmsg = StringProperty()

    def __init__(self, **kwargs):
        super(MainWidget, self).__init__(**kwargs)

    def deliver_payload(self, dt=0):
        if not dt: # called via on_press
            self.statusmsg = 'Busy launching Armageddon'
            # launch Armageddon here
            Clock.schedule_once(self.deliver_payload, 2)
        else: # scheduled via Clock
            self.manager.current = 'screen_one'


class MyApp(App):
    def build(self):
        mw=MainWidget() 
        return mw


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

但是,manager.current 是一个 Kivy StringProperty,我应该能够使用 set() 方法为其分配一个新值,并可能使用 Clock 来安排它,例如Clock.schedule_once(lambda dt: self.manager.property('current').set(??, 'screen_one'), 2)。 我无法找到 Kivy StringProperty set() 方法的文档。似乎该方法需要两个参数,第一个参数需要是 kivy._event.EventDispatcher 类型 - 根据我尝试一些随机猜测时得到的回溯信息。谁能指出一些文档或 set() 方法的使用示例?

编辑:我意识到我没有明确说明我最终想要做什么 - 我在问是否可以使用 Kivy Clock 来安排 Kivy 属性 set() 方法。例如,我可以像这样切换 Kivy BooleanProperty:

if self.property('myboolean').get(self):
    self.property('myboolean').set(self, False)
else:
    self.property('myboolean').set(self, True)

但我无法使用时钟来安排方法。以下行没有产生错误,但也没有任何效果:

Clock.schedule_once(lambda dt: self.property('myboolean').set(self, False),0)

在 Kivy StringProperty set() 方法的情况下,我什至无法弄清楚第一个参数需要是什么,所以没有尝试使用 Clock 来安排它。

进一步编辑: 尽管根据文档,屏幕管理器“当前”是 StringProperty,但它的行为似乎有所不同。使用 StringProperty 我可以执行以下操作:

self.property('statusmsg').set(self, 'Armageddon now')

但是,用 manager.current 尝试这样的事情不会成功:

self.manager.property('current').set(self.manager, 'aux_screen')

错误信息是:

   self.manager.property('current').set(self.manager, 'screen_one')
TypeError: Argument 'obj' has incorrect type (expected kivy._event.EventDispatcher, got kivy.weakproxy.WeakProxy)

令人困惑。

【问题讨论】:

    标签: string methods properties set kivy


    【解决方案1】:

    我偶然发现了这个Kivy: Changing screens in screen manager with an on_press event(谢谢你,Tshirtman),我现在有了一个答案。以下更改为我提供了我想要的 - 直接安排屏幕更改的能力(即无需调用中间方法):

    def deliver_payload(self):
        self.statusmsg = 'Busy launching Armageddon'
        Clock.schedule_once(lambda dt: self.manager.setter('current')(self.manager,'screen_one'), 2)
    

    看来,要为屏幕管理器的“当前”属性分配新值,正确使用的方法是“设置器”方法(而不是我尝试使用的“设置”方法)。

    【讨论】:

      【解决方案2】:

      您可以像在代码中所做的那样,通过简单地执行 self.manager.current = 'some string' 来为 StringProperty 设置新值。

      【讨论】:

      • 使用内置的 set() 方法可以让我直接使用 Clock 来安排值分配,无需任何包含 self.manager.current = 'some string' 分配的附加方法。它会更优雅..
      猜你喜欢
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-14
      相关资源
      最近更新 更多