在Kivy中,如何使用循环为一系列小部件设置动画?

时间:2017-09-20 01:09:28

标签: python animation kivy

我正在编写一个应用程序,其中我遇到了一种情况,我希望通过迭代for循环来依次为一系列对象设置动画。

当我运行应用程序并单击按钮时,我希望第一个标签文本缩小,等待1.5秒暂停,第二个标签缩小,等待,缩小,等待,缩小等。但是当它运行时,尽管应用程序在1.5秒的每一秒中都会休眠,但直到for循环运行它之后才会发生任何动画,然后它们都会立即运行。

我已从下面的主要代码中删除了问题代码,问题仍然存在。有没有人有解决方案或替代方案?我怀疑它与多线程有关,但这只是猜测。我尝试用@mainthread装饰 shrinkray ,但它似乎没有什么区别。

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.animation import Animation
from kivy.uix.button import Button
import time

class Test(GridLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)
        self.cols = 2
        self.thislabel1 = Label(text="One")
        self.add_widget(self.thislabel1)
        self.thislabel2 = Label(text="Two")
        self.add_widget(self.thislabel2)
        self.thislabel3 = Label(text="Three")
        self.add_widget(self.thislabel3)
        self.thislabel4 = Label(text="Four")
        self.add_widget(self.thislabel4)
        self.thislabel5 = Label(text='Five')
        self.add_widget(self.thislabel5)
        self.button1 = Button(text='Shrink Ray')
        self.button1.bind(on_release=self.shrinkray)
        self.add_widget(self.button1)
        self.these_children = [self.thislabel1,self.thislabel2,self.thislabel3,self.thislabel4,self.thislabel5]

    def shrinkray(self,*args):
        anim = Animation(font_size=1)
        for these_labels in self.these_children:
            anim.start(these_labels)
            time.sleep(1.5)


class MyApp(App):
    def build(self):
        return Test()

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

1 个答案:

答案 0 :(得分:0)

你是对的,你需要多线程。因为当你在主线程中循环并使用time.sleep()时,你的主要kivy循环会受到影响。但是,对于您的示例,您只需要一个额外的thread来运行循环,如下所示(按照注释):

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.animation import Animation
from kivy.uix.button import Button
import time
import threading

class Test(GridLayout):
    def __init__(self, **kwargs):
        super(Test, self).__init__(**kwargs)
        self.cols = 2
        self.thislabel1 = Label(text="One")
        self.add_widget(self.thislabel1)
        self.thislabel2 = Label(text="Two")
        self.add_widget(self.thislabel2)
        self.thislabel3 = Label(text="Three")
        self.add_widget(self.thislabel3)
        self.thislabel4 = Label(text="Four")
        self.add_widget(self.thislabel4)
        self.thislabel5 = Label(text='Five')
        self.add_widget(self.thislabel5)
        self.button1 = Button(text='Shrink Ray')
        self.button1.bind(on_release=self.shrinkstart)  # here the button targets the thread starter function
        self.add_widget(self.button1)
        self.these_children = [self.thislabel1,self.thislabel2,self.thislabel3,self.thislabel4,self.thislabel5]

    def shrinkstart(self, *args):
        t = threading.Thread(target=self.shrinkray)  # initiate the thread
        t.daemon = True  # daemon thread so it terminates when stopping the main thread
        t.start()  

    def shrinkray(self):
        anim = Animation(font_size=1)
        for these_labels in self.these_children:
            anim.start(these_labels)
            time.sleep(1.5)


class MyApp(App):
    def build(self):
        return Test()

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