如何从 Kivy 中的数组更新纹理?
How to update a texture from array in Kivy?
我是 Kivy 的新手,但已经看过教程。我想要一个包含从数组生成的纹理或图像的小部件,它会在每一帧发生变化。请参阅下面的内容,了解我目前拥有的内容。当我调整 window 大小时,当前行为是错误的——我认为旧的矩形永远不会被删除,但我不知道该怎么做。它还在主 window 左下角的默认 (100,100) 视图中显示相同的图像。我需要更改什么才能实现所需的行为,并且在调整 window?
大小时不会出现伪影
from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.layout import Layout
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import numpy as np
import random
class MainDisplay(Layout):
tex = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainDisplay, self).__init__(**kwargs)
Clock.schedule_once(self.texture_init, 0)
def texture_init(self, instance):
self.tex = Texture.create()
def update(self, dt):
size = 64 * 64 * 3
buf = np.array([int(random.random() * x * 255 / size) for x in range(size)])
print('update', max(buf), min(buf), np.mean(buf))
# then blit the buffer
self.tex.blit_buffer(buf.tostring(), colorfmt='bgr', bufferfmt='ubyte')
print('end update')
print(self.canvas)
print(self.size, self.pos, self, self.parent)
with self.canvas:
Rectangle(texture=self.tex, size=(self.width / 2, self.height / 2), pos=(self.center_x / 2, self.center_y / 2))
class MainWindow(BoxLayout):
md = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
def update(self, dt):
self.md.update(dt)
class ProtoApp(App):
def build(self):
mainWindow = MainWindow()
Clock.schedule_interval(mainWindow.update, 1.0/10.0)
return mainWindow
if __name__ == "__main__":
ProtoApp().run()
使用 proto.kv 文件:
<MainWindow>:
md: md
MainDisplay:
id: md
size_hint: (0.5, 0.5)
在此先感谢您的帮助!
问题
每当调整 window 的大小时,它都会创建新的矩形并留下前一个矩形的痕迹。
解决方案
使用canvas的内置函数,clear()
片段
def update(self, dt):
size = 64 * 64 * 3
buf = np.array([int(random.random() * x * 255 / size) for x in range(size)])
# then blit the buffer
self.tex.blit_buffer(buf.tostring(), colorfmt='bgr', bufferfmt='ubyte')
with self.canvas:
self.rect = Rectangle(texture=self.tex, size=(self.width / 2, self.height / 2),
pos=(self.center_x / 2, self.center_y / 2))
self.bind(pos=self.update_rect, size=self.update_rect)
def update_rect(self, *args):
self.canvas.clear()
self.rect.pos = self.pos
self.rect.size = self.size
我是 Kivy 的新手,但已经看过教程。我想要一个包含从数组生成的纹理或图像的小部件,它会在每一帧发生变化。请参阅下面的内容,了解我目前拥有的内容。当我调整 window 大小时,当前行为是错误的——我认为旧的矩形永远不会被删除,但我不知道该怎么做。它还在主 window 左下角的默认 (100,100) 视图中显示相同的图像。我需要更改什么才能实现所需的行为,并且在调整 window?
大小时不会出现伪影from kivy.app import App
from kivy.properties import ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.layout import Layout
from kivy.graphics import Rectangle
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import numpy as np
import random
class MainDisplay(Layout):
tex = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainDisplay, self).__init__(**kwargs)
Clock.schedule_once(self.texture_init, 0)
def texture_init(self, instance):
self.tex = Texture.create()
def update(self, dt):
size = 64 * 64 * 3
buf = np.array([int(random.random() * x * 255 / size) for x in range(size)])
print('update', max(buf), min(buf), np.mean(buf))
# then blit the buffer
self.tex.blit_buffer(buf.tostring(), colorfmt='bgr', bufferfmt='ubyte')
print('end update')
print(self.canvas)
print(self.size, self.pos, self, self.parent)
with self.canvas:
Rectangle(texture=self.tex, size=(self.width / 2, self.height / 2), pos=(self.center_x / 2, self.center_y / 2))
class MainWindow(BoxLayout):
md = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
def update(self, dt):
self.md.update(dt)
class ProtoApp(App):
def build(self):
mainWindow = MainWindow()
Clock.schedule_interval(mainWindow.update, 1.0/10.0)
return mainWindow
if __name__ == "__main__":
ProtoApp().run()
使用 proto.kv 文件:
<MainWindow>:
md: md
MainDisplay:
id: md
size_hint: (0.5, 0.5)
在此先感谢您的帮助!
问题
每当调整 window 的大小时,它都会创建新的矩形并留下前一个矩形的痕迹。
解决方案
使用canvas的内置函数,clear()
片段
def update(self, dt):
size = 64 * 64 * 3
buf = np.array([int(random.random() * x * 255 / size) for x in range(size)])
# then blit the buffer
self.tex.blit_buffer(buf.tostring(), colorfmt='bgr', bufferfmt='ubyte')
with self.canvas:
self.rect = Rectangle(texture=self.tex, size=(self.width / 2, self.height / 2),
pos=(self.center_x / 2, self.center_y / 2))
self.bind(pos=self.update_rect, size=self.update_rect)
def update_rect(self, *args):
self.canvas.clear()
self.rect.pos = self.pos
self.rect.size = self.size