Kivy 简明教程

Kivy - Bezier

在本章中,我们将创建一个 Kivy 应用程序,它将沿点列表交互绘制一条贝塞尔曲线。如果使用代码段算出的 x 和 y 坐标画一条闭合曲线,则所得图形类似于吃豆人字符:

from math import cos, sin, radians

x = y = 300
z = 200

self.points = [x, y]
for i in range(45, 360, 45):
   i = radians(i)
   self.points.extend([x + cos(i) * z, y + sin(i) * z])

   with self.layout.canvas:
      Color(1.0, 0.0, 1.0)
      self.line = Line(
         points=self.points + self.points[:2],
         dash_offset=10, dash_length=100
      )

它生成如下行模式:

kivy bezier

然后,我们使用相同点列表绘制一条贝塞尔曲线。

Color(1.0, 0.0, 1.0)
self.line = Line(
   points=self.points + self.points[:2],
   dash_offset=0,
   dash_length=100
)

线条和贝塞尔曲线将显示如下:

kivy bezier line

现在,我们希望动态地构造这两条曲线。随着每个滑块的值属性使用以下事件处理程序发生更改,我们使用两个滑块来更改线条指令和贝塞尔指令的破折号长度和偏移值:

def _set_bezier_dash_offset(self, instance, value):
   # effect to reduce length while increase offset
   self.bezier.dash_length = 100 - value
   self.bezier.dash_offset = value

def _set_line_dash_offset(self, instance, value):
   # effect to reduce length while increase offset
   self.line.dash_length = 100 - value
   self.line.dash_offset = value

最后,更改滑块值以查看两条曲线如何动态地重新绘制。

Example

complete code 如下所示 -

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.label import Label
from kivy.uix.slider import Slider
from kivy.graphics import Color, Bezier, Line
from kivy.core.window import Window

Window.size = (720,400)

class Main(App):
   title='Bezier Example'
   def _set_bezier_dash_offset(self, instance, value):
      # effect to reduce length while increase offset
      self.bezier.dash_length = 100 - value
      self.bezier.dash_offset = value

   def _set_line_dash_offset(self, instance, value):
      # effect to reduce length while increase offset
      self.line.dash_length = 100 - value
      self.line.dash_offset = value

   def build(self):
      from math import cos, sin, radians
      x = y = 300
      z = 200
      # Pacman !
      self.points = [x, y]
      for i in range(45, 360, 45):
         i = radians(i)
         self.points.extend([x + cos(i) * z, y + sin(i) * z])
      print (self.points)
      self.layout = FloatLayout()

      with self.layout.canvas:
         Color(1.0, 0.0, 0.0)

         self.bezier = Bezier(
            points=self.points, segments=150, loop=True,
            dash_length=100, dash_offset=10
         )

         Color(1.0, 0.0, 1.0)
         self.line = Line(
            points=self.points + self.points[:2],
            dash_offset=10,
            dash_length=100)
      l1=Label(
         text='Beizer offset', pos_hint={'x':.1},
         size_hint=(.1, None), height=50
      )
      self.layout.add_widget(l1)

      s1 = Slider(
         y=0, pos_hint={'x': .3},
         size_hint=(.7, None), height=50
      )
      self.layout.add_widget(s1)
      s1.bind(value=self._set_bezier_dash_offset)

      l2=Label(
         text='Line offset', y=50, pos_hint={'x':.1},
         size_hint=(.1, None), height=50
      )
      self.layout.add_widget(l2)

      s2 = Slider(
         y=50, pos_hint={'x': .3},
         size_hint=(.7, None), height=50
      )
      self.layout.add_widget(s2)
      s2.bind(value=self._set_line_dash_offset)

      return self.layout

if __name__ == '__main__':
   Main().run()

Output

以下屏幕截图显示了两个不同滑块位置的曲线:

kivy bezier curves
kivy bezier offset