【问题标题】:How to create a lap function for a countdown timer in Kivy如何在 Kivy 中为倒数计时器创建圈数功能
【发布时间】:2019-06-25 09:41:05
【问题描述】:

我有一个倒计时计时器,它从 randint() 参数给定范围内的随机整数开始,倒计时到零。目的是使计时器在第一次达到零时以新的随机数重新启动(即圈功能),并在第二次达到零时显示“FINISH”。

这是我第一次使用 kivy,如果解决方案很明显,请见谅。目前我只需要两次迭代,但我可能需要稍后调整它,以便计时器在最终停止之前可以运行任意次数。圈数将在运行应用程序之前在代码中确定,而不是由应用程序用户在运行应用程序时确定。

from kivy.app import App
from kivy.uix.label import Label
from kivy.animation import Animation
from kivy.properties import NumericProperty
from random import randint


class IncrediblyCrudeClock(Label):
    for i in range(2):
        r=randint(3,7)
        a = NumericProperty(r)  # Number of seconds to countdown


        def start(self):  #Function to initiate the countdown
            Animation.cancel_all(self)  # stop any current animations
            self.anim = Animation(a=0, duration=self.a)  #a=0 sets the 
#final destination of a. duration sets the time taken to reach stopping 
#point (i.e 5 seconds for a=5)
            def finish_callback(animation, incr_crude_clock):
                if self.i==1:
                    incr_crude_clock.text = "FINISHED"  #when the clock 
#reaches zero, display "FINISHED"
            self.anim.bind(on_complete=finish_callback)  #call the 
#finish_callback function once a=0
            self.anim.start(self)  #Start the animation (otherwise clock 
#stuck at 5 for a=5)


class TimeApp(App):
    def build(self):
        crudeclock = IncrediblyCrudeClock()
        crudeclock.start()
        return crudeclock

if __name__ == "__main__":
    TimeApp().run()



<IncrediblyCrudeClock>
    text: str(round(self.a, 1))

应用在第一次倒计时时确实按预期运行。选择一个随机数,计时器倒计时至零,但在第一次倒计时后它会停止并显示“已完成”。似乎 for 循环在应用程序实际启动之前从零迭代到一,因此,当倒计时开始时, i 已经等于 1(而不是先从 a 运行到零,并且 i=0 和然后在 i=1 的情况下从新的 a 到零)。我想这是因为 for 循环在错误的位置(即不是在调用 start 函数时),但我一直无法弄清楚如何纠正这个问题。 这也是我第一次使用堆栈溢出,所以如果您需要了解其他信息,请告诉我。

【问题讨论】:

    标签: python timer kivy kivy-language


    【解决方案1】:

    这是一个重复倒计时指定次数的版本:

    from random import randint
    from kivy.animation import Animation
    from kivy.app import App
    from kivy.lang import Builder
    from kivy.properties import NumericProperty
    from kivy.uix.label import Label
    
    
    class IncrediblyCrudeClock(Label):
        a = NumericProperty(0)  # Number of seconds to countdown
    
        def __init__(self, **kwargs):
            self.max_laps = kwargs.pop('laps', 2)  # default is to do 2 laps
            self.lap_counter = 0
            super(IncrediblyCrudeClock, self).__init__(**kwargs)
    
        def start(self, *args):
            self.lap_counter += 1
            self.a = randint(3, 7)
            self.anim = Animation(a=0, duration=self.a)
            if self.lap_counter >= self.max_laps:
                # this is the last lap, set on_complete to call self.finish_callback
                self.anim.bind(on_complete=self.finish_callback)
            else:
                # not finished yet, call self.start again
                self.anim.bind(on_complete=self.start)
            print('starting anim number', self.lap_counter)
            self.anim.start(self)
    
        def finish_callback(self, animation, incr_crude_clock):
            print('in finish_callback')
            self.text = 'FINISHED'
    
    Builder.load_string('''
    <IncrediblyCrudeClock>
        text: str(round(self.a, 1))
    ''')
    
    
    class TimeApp(App):
        def build(self):
            # specify the number of repetitions in the constructor
            crudeclock = IncrediblyCrudeClock(laps=3)
            crudeclock.start()
            return crudeclock
    
    if __name__ == "__main__":
        TimeApp().run()
    

    【讨论】:

    • 太好了,谢谢!你介意向我解释一下 init__() 函数中的 pop() 和 super() 方法在做什么吗?我目前的理解是 pop() 可用于从列表中删除特定元素,而 super() 用于从父类继承。似乎 pop 函数将 max_laps 设置为关键字参数,但我不确定如何?此外,在这种情况下,是否使用 super() 方法将 __init 函数的参数设置为 IncrediblyCrudeClock() 类的参数?提前致谢
    • kwargs 是传递给__init__() 方法的关键字参数的字典。 popmax_laps 的值设置为传入的值(如果没有提供laps 关键字,则设置为2)。它还会从kwargs 字典中删除laps 键,这样Label__init__() 就不会遇到意外的关键字。当您在子类中包含自己的__init__() 时,它会覆盖超类__init__(),并且大多数类必须执行自己的__init__() 才能正常工作。 super 调用Label__init__()
    【解决方案2】:

    很难理解您的代码,但这是您的 IncrediblyCrudeClock 的一个有效版本:

    class IncrediblyCrudeClock(Label):
        a = NumericProperty(0)  # Number of seconds to countdown
    
        def start(self):
            self.a = randint(3, 7)
            self.anim = Animation(a=0, duration=self.a)
            self.anim.bind(on_complete=self.secondAnim)
            print('starting first anim')
            self.anim.start(self)
    
        def secondAnim(self, animation, incr_crude_clock):
            self.a = randint(3, 7)
            self.anim = Animation(a=0, duration=self.a)
            self.anim.bind(on_complete=self.finish_callback)
            print('starting second anim')
            self.anim.start(self)
    
        def finish_callback(self, animation, incr_crude_clock):
            print('in finish_callback')
            self.text = 'FINISHED'
    

    这是一个非常简单的方法。我确信startsecondAnim 方法可以组合为一种方法,具有更多的逻辑性。

    【讨论】:

    • 谢谢,这很有帮助。你能给我一些关于如何结合第一种和第二种方法的指示吗?我过去使用过 Spyder,重复预定次数的过程只需要一个简单的 for 循环,但我不知道如何在这里实现这种方法。我最终会要求程序在文本输入小部件中重复用户输入指定的一定次数。
    猜你喜欢
    • 2020-10-27
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    相关资源
    最近更新 更多