我正在尝试编写一个程序,该程序将具有从matplotlib生成的动画。这个想法是将Rectangle写到画布上,并使用blit_buffer更新其纹理。因此,在调用app.run()之后,外部线程会调用Rectangle的update函数来更新该纹理。
有问题的主类,其中static_spin_globe_arr是一个numpy数组
class SpinGlobeRectangle(Rectangle):
def __init__(self, **kwargs):
super(SpinGlobeRectangle, self).__init__(**kwargs)
self.lon_float = 0
self.lon_idx = 0
self.spin_speed = 5.5
self.texture = Texture.create(size=(400, 400), colorfmt='rgba')
self.spin_update(time_delta=0)
def spin_update(self, time_delta):
self.lon_float += 360 * time_delta / self.spin_speed
if self.lon_float >= 360:
self.lon_float -= 360
self.lon_idx = round(self.lon_float * static_spin_globe_arr.shape[0] / 360) % static_spin_globe_arr.shape[0]
self.texture.blit_buffer(static_spin_globe_arr[self.lon_idx, :, :, :].tostring(), colorfmt='rgba', bufferfmt='ubyte')
# self.pos = (self.pos[0]+1,self.pos[1])
相关标题屏幕课程
class TitleScreen(Screen):
def __init__(self, window_size, **kwargs):
super(TitleScreen, self).__init__(**kwargs)
self.layout = FloatLayout(size_hint=(1, 1))
self.add_widget(self.layout)
btn_spacing = 5
btn_height = 40
btn_width = 300
title_bar_size = (btn_width, 3 * (btn_spacing + btn_height) - btn_spacing)
title_bar_pos = (2 * btn_spacing, (window_size[1] - title_bar_size[1]) / 2)
self.title_bar_layout = BoxLayout(size=title_bar_size, pos=title_bar_pos, size_hint=(None, None), orientation='vertical', spacing=btn_spacing)
self.layout.add_widget(self.title_bar_layout)
self.new_game_button = Button(text='x', font_size=14)
self.load_game_button = Button(text='y', font_size=14)
self.credits_game_button = Button(text='z', font_size=14)
self.title_bar_layout.add_widget(self.new_game_button)
self.title_bar_layout.add_widget(self.load_game_button)
self.title_bar_layout.add_widget(self.credits_game_button)
with self.canvas.before:
Color(0,.5,.5, mode='rgb')
self.background_rect = Rectangle(size=window_size)
glb_size = (window_size[0] - title_bar_size[0] - 8 * btn_spacing,) * 2
glb_pos = (window_size[0] - 2 * btn_spacing - glb_size[0], (window_size[1] - glb_size[1]) / 2)
Color(1, 1, 1, mode='rgb')
self.spin_globe_rect = SpinGlobeRectangle(size=glb_size, pos=glb_pos)
相关的应用定义
class AeroSimApp(App):
def __init__(self, title, window_size, **kwargs):
super(AeroSimApp, self).__init__(**kwargs)
self.screenManager = ScreenManager()
self.loadScreen = LoadScreen(name='LOAD_SCREEN', window_size=window_size)
self.titleScreen = TitleScreen(name='TITLE_SCREEN', window_size=window_size)
self.mainScreen = MainScreen(name='MAIN_SCREEN', window_size=window_size)
self.screenManager.add_widget(self.loadScreen)
self.screenManager.add_widget(self.titleScreen)
self.screenManager.add_widget(self.mainScreen)
self.screenManager.current = 'LOAD_SCREEN'
# self.screenManager.current_screen = 'LOAD_SCREEN'
Window.size = window_size
# kivy.config.Config.set('graphics', 'width', window_size[0])
# kivy.config.Config.set('graphics', 'height', window_size[1])
# kivy.config.Config.write()
self.title = title
def build(self):
return self.screenManager
如何从外部线程调用该类(该类封装在循环中)
def doTitleScreenGraphics(self, first_loop, time_delta):
self.kivyApp.titleScreen.spin_globe_rect.spin_update(time_delta=time_delta)
self.kivyApp.titleScreen.canvas.ask_update()
我一直在尝试各种GUI库,但尚未决定使用kivy。我不想将所有功能都移到应用程序代码中。
我运行了程序,外线程通过了spin_update函数,但是纹理没有改变。当我取消注释更改pos的行时,矩形pos在屏幕上更新。如何实现纹理变化?
一个次要的但不那么重要的问题是,如何在所需的时间间隔内最好地实现这一更改,在此时间间隔内所有对象都被更新?我不认为我目前正在这样做。
我看过Updating a textured rectangle in Kivy after the texture changes,这似乎是我的问题,但是坦率地说,我不理解ObjectProperty类,也不想使用Kivy的Clock类,因为我已经有了一个有效的设置没有显示在提供的代码中。
编辑:我也看过How to update a texture from array in Kivy?,但是每帧重新创建对象似乎很浪费。 (编辑:所以我尝试了这个,充其量只有一个黑色的矩形。否则,崩溃或没有更新图像)
编辑:我现在认为In Kivy, is there a way to dynamically change the shape of a texture?是我想要的。我正在研究它,但是文档令人困惑。
编辑:我看不到没有在应用程序的构建函数中涉及时钟的方法,并且将我的一些代码合并到kivy代码中(因为同一任务的两个时钟是多余的)。 :(积极地说,似乎需要在时钟内完成的唯一一行是重载函数调用,因此使用Clock.schedule_once(self.kivyApp.custom_update)可能必须这样做。:/
类似...
def update(self, dt):
self.titleScreen.spin_globe_rect.spin_update(dt)
self.titleScreen.spin_globe_rect.reload(self.titleScreen.spin_globe_rect.texture)
self.titleScreen.canvas.ask_update()
pass
def build(self):
Clock.schedule_interval(self.update, 1/30)
return self.screenManager
SpinGlobeRectangle已更新为
的位置class SpinGlobeRectangle(Rectangle):
def __init__(self, **kwargs):
super(SpinGlobeRectangle, self).__init__(**kwargs)
self.lon_float = 0
self.lon_idx = 0
self.spin_speed = 5.5
self.texture = Texture.create(size=(400, 400), colorfmt='rgba')
self.spin_update(time_delta=0)
def spin_update(self, time_delta):
self.lon_float += 360 * time_delta / self.spin_speed
if self.lon_float >= 360:
self.lon_float -= 360
self.lon_idx = round(self.lon_float * static_spin_globe_arr.shape[0] / 360) % static_spin_globe_arr.shape[0]
self.reload(self.texture)
def reload(self, texture):
texture.blit_buffer(static_spin_globe_arr[self.lon_idx, :, :, :].tostring(), colorfmt='rgba', bufferfmt='ubyte')