Kivy 简明教程

Kivy - Framebuffer

Kivy 库提供了一个“Fbo”类,该类表示帧缓冲区外屏。这是一个非屏幕窗口,您可以在其上绘制任何图形指令,然后将其用作某个 Kivy 小部件的画布的纹理。

Fbo 类在 kivy.graphics.fbo 模块中定义。第一步是创建 fbo 并在其他矩形上使用 fbo 纹理。

from kivy.graphics import Fbo, Color, Rectangle
with self.canvas:
   self.fbo = Fbo(size=self.size)

接下来,将图形指令(例如 Rectangle)添加到 Fbo 对象。例如 -

with self.fbo:
   Color(1, 0, 0, .8)
   Rectangle(size=(256, 64))
   Color(0, 1, 0, .8)
   Rectangle(size=(64, 256))

最后,将 Fbo 纹理应用到画布。

self.texture = self.fbo.texture

请注意,如果 OpenGL 上下文丢失,FBO 也会丢失。在这种情况下,你需要使用 Fbo.add_reload_observer() 方法重新上传数据。

add_reload_observer(callback) − 添加一个回调,用于在整个图形上下文重新加载后调用。回调参数将是上下文本身。

bind() 方法将 FBO 对象绑定到当前的 opengl 上下文。这样,所有绘图操作都将在帧缓冲区内进行,直到调用 release() 。release() 方法释放或解除帧缓冲区的绑定。

self.fbo = FBO()
self.fbo.bind()

# do any drawing command
self.fbo.release()

self.canvas = self.fbo.texture

还有一个 remove_reload_observer(callback) 方法,它从观察者列表中删除一个回调,该回调之前由 add_reload_observer() 添加。

clear_buffer()clear_color 方法以 (red, green, blue, alpha) 格式清除帧缓冲区和清除颜色。

Example

以下代码演示了如何在 Kivy 应用程序中使用 Framebuffer。代码的重要部分是一个名为 FboFloatLayout 的类,它继承了 Kivy 的 FloatLayout 类。

构造方法 ( init () 方法) 在浮动布局的画布上创建了 Fbo 对象,并在其上绘制了一个矩形,并将其纹理设置为画布的纹理。

def __init__(self, **kwargs):
   self.canvas = Canvas()
   with self.canvas:
      self.fbo = Fbo(size=self.size)
      self.fbo_color = Color(1, 1, 1, 1)
      self.fbo_rect = Rectangle()

   with self.fbo:
      ClearColor(0, 0, 0, 0)
      ClearBuffers()

   self.texture = self.fbo.texture
   super(FboFloatLayout, self).__init__(**kwargs)

我们将为这个 FloatLayout 类添加一个按钮,但在添加该按钮之前,重写了 add_widget() 方法,以便将图形指令添加到 fbo,然后将其添加到画布。

def add_widget(self, *args, **kwargs):
   canvas = self.canvas
   self.canvas = self.fbo
   ret = super(FboFloatLayout, self).add_widget(*args, **kwargs)
   self.canvas = canvas
   return ret

FboFloatLayout 类还具有对大小、位置和纹理变化做出响应的回调。

def on_size(self, instance, value):
   self.fbo.size = value
   self.texture = self.fbo.texture
   self.fbo_rect.size = value

def on_pos(self, instance, value):
   self.fbo_rect.pos = value

def on_texture(self, instance, value):
   self.fbo_rect.texture = value

现在进入 App 类。build() 方法添加了一个按钮,并应用了一系列动画效果,使按钮在重复的情况下位置从上到下、从右到左发生变化。

def anim_btn(*args):
   animate = Animation(pos=(b.pos[0], Window.height - 50))
   animate += Animation(pos=(b.pos[0], 0))
   animate += Animation(pos_hint={'center_x': 1})
   animate += Animation(pos_hint={'center_x': 0})
   animate += Animation(pos_hint={'center_x': .5})
   animate.start(b)
   animate.repeat = True

b.bind(on_press=anim_btn)

出于方便考虑,这些代码片段被整理在了 complete code 清单中 −

from kivy.graphics import Color, Rectangle, Canvas,
ClearBuffers, ClearColor
from kivy.graphics.fbo import Fbo
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.properties import ObjectProperty, NumericProperty
from kivy.app import App
from kivy.animation import Animation
from kivy.core.window import Window

Window.size = (720, 400)

class FboFloatLayout(FloatLayout):
   texture = ObjectProperty(None, allownone=True)

   def __init__(self, **kwargs):
      self.canvas = Canvas()
      with self.canvas:
         self.fbo = Fbo(size=self.size)
         self.fbo_color = Color(1, 1, 1, 1)
         self.fbo_rect = Rectangle()

      with self.fbo:
         ClearColor(0, 0, 0, 0)
         ClearBuffers()

      self.texture = self.fbo.texture
      super(FboFloatLayout, self).__init__(**kwargs)

   def add_widget(self, *args, **kwargs):
      canvas = self.canvas
      self.canvas = self.fbo
      ret = super(FboFloatLayout, self).add_widget(*args, **kwargs)
      self.canvas = canvas
      return ret

   def on_size(self, instance, value):
      self.fbo.size = value
      self.texture = self.fbo.texture
      self.fbo_rect.size = value

   def on_pos(self, instance, value):
      self.fbo_rect.pos = value

   def on_texture(self, instance, value):
      self.fbo_rect.texture = value

class FBOdemoApp(App):
   def build(self):
      f = FboFloatLayout()
      b = Button(text="FBO", size_hint=(None, None), pos_hint={'center_x': .5})
      f.add_widget(b)

      def anim_btn(*args):
         animate = Animation(pos=(b.pos[0], Window.height - 50))
         animate += Animation(pos=(b.pos[0], 0))
         animate += Animation(pos_hint={'center_x': 1})
         animate += Animation(pos_hint={'center_x': 0})
         animate += Animation(pos_hint={'center_x': .5})
         animate.start(b)
         animate.repeat = True
      b.bind(on_press=anim_btn)
      return f

FBOdemoApp().run()

Output

应用程序启动时,底部有一个带有 FBO 标题的按钮。单击时,它会按照定义开始动画效果。

kivy framebuffer