【问题标题】:In Kivy, how can I animate a series of widgets with a loop?在 Kivy 中,如何使用循环为一系列小部件设置动画?
【发布时间】:2017-09-20 01:09:28
【问题描述】:

我正在编写一个应用程序,在该应用程序中我遇到了一种情况,我想通过迭代 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()

【问题讨论】:

    标签: python animation kivy


    【解决方案1】:

    你是对的,你需要多线程。因为当您循环并在主线程中使用 time.sleep() 时,您的主 kivy 循环会受到影响。但是,以您为例,您只需要一个额外的thread 即可运行如下循环(遵循 cmets):

    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()
    

    【讨论】:

    • 完美!非常感谢您的快速输入。我将开始深入研究有关线程的文档,以便更好地掌握这一点
    猜你喜欢
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多