每次调用时如何重新启动 kivy 动画?
How can I restart kivy animation every time its called upon?
我正在制作一个简单的天气应用程序。用户输入一个位置并以纯文本形式获得结果。我制作了一个带有旋转动画的加载屏幕。当程序加载这些天气结果时,它会切换到加载屏幕并且动画旋转得很好。
我现在将动画设置为 20 秒。这允许我的加载屏幕的第一个实例显示足够的时间来产生结果,然后切换到结果屏幕(通常大约 5 秒)。看起来效果不错。
我的问题是:一旦动画完成 20 秒 运行(在后台),再次调用时它不会重新启动。该应用程序似乎只允许调用一次。要再次激活,应用必须完全关闭并重新启动。
理想情况下,我希望动画停止旋转并在加载屏幕退出后立即重置(因此一旦结果已交付)。用户可以多次获取天气,所以我需要在每次显示加载屏幕时重新开始。
我已经尝试了让它在后台不断旋转的不受欢迎的解决方案,这样当显示加载屏幕时,它就会旋转。
但是,即使那样我也很难让它重复...(anim.repeat = True
对我不起作用)
这是一个工作示例,它已被尽可能地剥离,但仍然与我的真实应用程序一样。
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.animation import Animation
import time
from threading import Thread
class HomeScreen(Screen):
pass
class Results1Screen(Screen):
pass
class LoadScreen(Screen):
pass
GUI = Builder.load_file("main.kv")
class TestApp(App):
def build(self):
return GUI
def change_screen(self, screen_name):
screen_manager = self.root.ids['screen_manager']
screen_manager.current = screen_name
def spin_widget(self):
widget = self.root.ids["load_screen"].ids["spinning_widget"]
anim = Animation(angle=-2000, duration=20)
anim.repeat = True # this doesn't seem to work?
anim.start(widget)
def thread1(self): # this starts the actual "work" of the app by calling get_briefing() below
p2 = Thread(target=lambda: self.get_briefing())
p2.start()
def get_briefing(self):
time.sleep(5)# I have added a 5sec sleep to emulate work being done
self.change_screen("results_1_screen") # screen change from loading screen to results screen after work complete
TestApp().run()
main.kv(仅用于屏幕管理)
#:import utils kivy.utils
#:include kv/homescreen.kv
#:include kv/results1screen.kv
#:include kv/loadscreen.kv
GridLayout:
cols: 1
FloatLayout:
canvas:
Rectangle:
size: self.size
pos: self.pos
pos_hint: {"top": 1, "left": 1}
size_hint: 1, 0
ScreenManager:
id: screen_manager
HomeScreen:
name: "home_screen"
id: home_screen
Results1Screen:
name: "results_1_screen"
id: results_1_screen
LoadScreen:
name: "load_screen"
id: load_screen
homescreen.kv
<HomeScreen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#000523")
Rectangle:
size: self.size
pos: self.pos
Button:
text: "GO!"
pos_hint: {"top": .2, "center_x": .5}
size_hint: .5, .08
padding: 20, 20
on_release:
app.spin_widget()
app.change_screen("load_screen") # widget spinning and going to load screen
app.thread1() # start the app working in background
results1screen.kv(在实际应用中,这显示了所需的结果)
<Results1Screen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#000523")
Rectangle:
size: self.size
pos: self.pos
Label:
text: "RESULTS"
pos_hint: {"top": .9, "center_x": .5}
size_hint: 1, .1
Button:
text: "back"
size_hint: .1, .1
on_release:
app.change_screen("home_screen")
loadscreen.kv
<LoadScreen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#000523")
Rectangle:
size: self.size
pos: self.pos
Label:
text: "loading"
SpinningWidget:
id: spinning_widget
angle: 0
size_hint: .1, .1
pos_hint: {"center_x": .5, "center_y": .6}
<SpinningWidget@Image>
angle: 0
canvas.before:
PushMatrix
Rotate:
angle: root.angle
axis: 0, 0, 1
origin: root.center
canvas.after:
PopMatrix
在 get_briefing
功能完成后,我尝试了几种退出或重置旋转小部件功能的方法,但无济于事。我已经尝试 anim.cancel()
和 exit(self.spin_widget())
之类的东西试图重置它,为下一次调用做好准备。
有人可以帮我解决这个问题吗,我似乎无法在 Kivy 文档或其他任何在线网站上找到答案。谢谢。
尝试在每个 Animation
:
之前将 angle
重置为 0
def spin_widget(self):
widget = self.root.ids["load_screen"].ids["spinning_widget"]
widget.angle = 0
anim = Animation(angle=-2000, duration=20)
anim.repeat = True # this doesn't seem to work?
anim.start(widget)
问题是在第一个 Animation
之后,angle
的值是 -2000
,所以之后的任何 Animation
实际上都不会改变角度。 repeat
.
同样的问题
我正在制作一个简单的天气应用程序。用户输入一个位置并以纯文本形式获得结果。我制作了一个带有旋转动画的加载屏幕。当程序加载这些天气结果时,它会切换到加载屏幕并且动画旋转得很好。
我现在将动画设置为 20 秒。这允许我的加载屏幕的第一个实例显示足够的时间来产生结果,然后切换到结果屏幕(通常大约 5 秒)。看起来效果不错。
我的问题是:一旦动画完成 20 秒 运行(在后台),再次调用时它不会重新启动。该应用程序似乎只允许调用一次。要再次激活,应用必须完全关闭并重新启动。
理想情况下,我希望动画停止旋转并在加载屏幕退出后立即重置(因此一旦结果已交付)。用户可以多次获取天气,所以我需要在每次显示加载屏幕时重新开始。
我已经尝试了让它在后台不断旋转的不受欢迎的解决方案,这样当显示加载屏幕时,它就会旋转。
但是,即使那样我也很难让它重复...(anim.repeat = True
对我不起作用)
这是一个工作示例,它已被尽可能地剥离,但仍然与我的真实应用程序一样。
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.animation import Animation
import time
from threading import Thread
class HomeScreen(Screen):
pass
class Results1Screen(Screen):
pass
class LoadScreen(Screen):
pass
GUI = Builder.load_file("main.kv")
class TestApp(App):
def build(self):
return GUI
def change_screen(self, screen_name):
screen_manager = self.root.ids['screen_manager']
screen_manager.current = screen_name
def spin_widget(self):
widget = self.root.ids["load_screen"].ids["spinning_widget"]
anim = Animation(angle=-2000, duration=20)
anim.repeat = True # this doesn't seem to work?
anim.start(widget)
def thread1(self): # this starts the actual "work" of the app by calling get_briefing() below
p2 = Thread(target=lambda: self.get_briefing())
p2.start()
def get_briefing(self):
time.sleep(5)# I have added a 5sec sleep to emulate work being done
self.change_screen("results_1_screen") # screen change from loading screen to results screen after work complete
TestApp().run()
main.kv(仅用于屏幕管理)
#:import utils kivy.utils
#:include kv/homescreen.kv
#:include kv/results1screen.kv
#:include kv/loadscreen.kv
GridLayout:
cols: 1
FloatLayout:
canvas:
Rectangle:
size: self.size
pos: self.pos
pos_hint: {"top": 1, "left": 1}
size_hint: 1, 0
ScreenManager:
id: screen_manager
HomeScreen:
name: "home_screen"
id: home_screen
Results1Screen:
name: "results_1_screen"
id: results_1_screen
LoadScreen:
name: "load_screen"
id: load_screen
homescreen.kv
<HomeScreen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#000523")
Rectangle:
size: self.size
pos: self.pos
Button:
text: "GO!"
pos_hint: {"top": .2, "center_x": .5}
size_hint: .5, .08
padding: 20, 20
on_release:
app.spin_widget()
app.change_screen("load_screen") # widget spinning and going to load screen
app.thread1() # start the app working in background
results1screen.kv(在实际应用中,这显示了所需的结果)
<Results1Screen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#000523")
Rectangle:
size: self.size
pos: self.pos
Label:
text: "RESULTS"
pos_hint: {"top": .9, "center_x": .5}
size_hint: 1, .1
Button:
text: "back"
size_hint: .1, .1
on_release:
app.change_screen("home_screen")
loadscreen.kv
<LoadScreen>:
FloatLayout:
canvas:
Color:
rgb: utils.get_color_from_hex("#000523")
Rectangle:
size: self.size
pos: self.pos
Label:
text: "loading"
SpinningWidget:
id: spinning_widget
angle: 0
size_hint: .1, .1
pos_hint: {"center_x": .5, "center_y": .6}
<SpinningWidget@Image>
angle: 0
canvas.before:
PushMatrix
Rotate:
angle: root.angle
axis: 0, 0, 1
origin: root.center
canvas.after:
PopMatrix
在 get_briefing
功能完成后,我尝试了几种退出或重置旋转小部件功能的方法,但无济于事。我已经尝试 anim.cancel()
和 exit(self.spin_widget())
之类的东西试图重置它,为下一次调用做好准备。
有人可以帮我解决这个问题吗,我似乎无法在 Kivy 文档或其他任何在线网站上找到答案。谢谢。
尝试在每个 Animation
:
angle
重置为 0
def spin_widget(self):
widget = self.root.ids["load_screen"].ids["spinning_widget"]
widget.angle = 0
anim = Animation(angle=-2000, duration=20)
anim.repeat = True # this doesn't seem to work?
anim.start(widget)
问题是在第一个 Animation
之后,angle
的值是 -2000
,所以之后的任何 Animation
实际上都不会改变角度。 repeat
.