How to update a texture from array in Kivy?

允我心安 提交于 2019-12-25 01:47:25

问题


I'm new to Kivy, but have watched the tutorials. I want to have a widget containing a texture or image generated from an array, which will change at each frame. See below for what I currently have. Current behaviour is wrong when I resize the window - I think that the old Rectangle is never being deleted, but I can't see how to do that. It also shows the same image in a default (100,100) view at the bottom left of the main window. What do I need to change to achieve the desired behaviour, and not get artifacts when resizing the 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()

with the proto.kv file:

<MainWindow>:
    md: md
    MainDisplay:
        id: md
        size_hint: (0.5, 0.5)

Thanks in advance for your help!


回答1:


Problem

Whenever the window is resized, it is creating new rectangle and leaving traces of the previous one.

Solution

Use the canvas's built-in function, clear()

Snippets

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


来源:https://stackoverflow.com/questions/55099463/how-to-update-a-texture-from-array-in-kivy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!