Kivy 简明教程
Kivy - Graphics
Kivy 框架配备了强大图形功能,该功能构建在 OpenGL 和 SDL 指令之上。像许多图形工具包一样,Kivy 提供可以渲染图形的画布。然而,Kivy 的画布不同于在其他框架中发现的 Canvas 对象,例如 HTML5 中的 Canvas 甚至 Python 的 Tkinter 库中的 Canvas。让我们尝试理解在 Kivy 中使用图形的不同之处。
在 Kivy 中,图形画布是一组绘图指令,它们定义了小部件的图形表示,你可以将它们视为无限绘图板。尽管 Kivy 库中的每个 GUI 小部件都有一个 Canvas,但是所有 Kivy 小部件共享相同的坐标空间,你可以在这个空间中绘制。该坐标空间不受窗口或应用程序窗口大小的限制,以便我们甚至可以在可见区域外进行绘制。
Kivy 中有两种类型的图形指令 -
-
Vertex instructions - 用于绘制基本几何形状(如线条、矩形、椭圆等)的指令称为顶点指令。
-
Context instructions - 这些指令不绘制任何内容,但是会操控整个坐标空间,以便向其添加颜色,进行旋转、平移和缩放。
某个上下文指令对画布对象的影响 - 例如,如果我们对按钮的画布应用旋转指令,则会影响所有后续图形指令,这是因为所有小部件在坐标空间中共享。
Vertex Instructions
OpenGL 使用顶点来描述其图形对象。顶点指令是用于绘制图形的指令。常见的顶点指令包括点、线、三角形、矩形、椭圆、网格、贝塞尔曲线等。章节 Kivy - 绘制详细解释了绘图指令的用法。
Rotate
旋转指令在对象画布的上下文中起作用。对象以给定角度沿给定轴进行旋转。
with self.canvas:
rotate = Rotate(angle=45)
旋转是根据传给它的参数执行的。
-
angle - 用于获取/设置旋转角度的属性。范围介于 0 至 360
-
axis - 用于获取/设置旋转轴的属性。轴的格式是 (x, y, z)。
-
origin - 旋转的原点。原点的格式可以为 (x, y) 或 (x, y, z)。
-
set(float angle, float ax, float ay, float az) - 此函数设置旋转角度和旋转轴。
Scale
Scale 指令在对象的画布环境中运行。它根据比例因子在给定轴线上更改对象的大小。
with self.canvas:
s=Scale(2,2,1)
使用一个或三个自变量创建 Scale 指令 -
Scale(x, y, z)
Scale 指令接受以下参数 -
origin - 缩放原点。原点的格式可以为 (x, y) 或 (x, y, z)。
-
x - 获取/设置 X 轴上缩放属性。
-
y - 获取/设置 Y 轴上缩放属性。
-
z - 获取/设置 Z 轴上缩放属性。
-
xyz - x、y 和 z 轴上的 3D 三元组比例向量。
特定对象画布中的缩放和旋转指令会导致整个画布发生变化,因为画布共享相同的坐标空间。因此,若要检索其他窗口小部件的位置和状态,则有 PushMatrix
和 PopMatrix
指令。
-
PushMatrix 保存当前坐标空间环境。
-
PopMatrix 检索上次保存的坐标空间环境。
因此,被 PushMatrix
和 PopMatrix
包围的变换指令(缩放、旋转和转换)不会影响界面中其他内容。
Example
我们从在应用程序窗口中放置一个标签和两个按钮开始。我们使用 FloatLAyout
,它让我们可以在特定坐标中放置指定大小的窗口小部件。
通过在其画布上绘制彩色矩形,为标签提供一个背景颜色 -
self.lbl = Label(
text= 'Hello World', font_size=24,
halign='center',size_hint=(.2, .1),
pos=(300, 250)
)
with self.lbl.canvas:
Color(0, 1, 0, 0.25)
Rectangle(pos=self.lbl.pos, size=(200,50))
按钮标题“旋转”绑定到 update_rotate()
方法,该方法应用一个 45 度的旋转。请注意,PushMatrix
在旋转之前存储坐标空间,并在旋转之后调用 PopMatrix
。
def update_rotate(self, instance):
with self.lbl.canvas.before:
PushMatrix()
rotate = Rotate(angle=45)
with self.lbl.canvas.after:
PopMatrix()
rotate.origin = self.lbl.center
当单击“缩放”按钮时,它将使“旋转”按钮沿 X 轴和 Y 轴缩放。用于该目的的 update_scale()
方法如下 -
def update_scale(self, instance):
with self.btn.canvas.before:
PushMatrix()
s = Scale(2, 2, 1)
with self.btn.canvas.after:
PopMatrix()
s.origin = self.btn.center
complete example code 如下 -
from kivy.app import App
from kivy.graphics import *
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.core.window import Window
Window.size = (720, 400)
class RotationApp(App):
def update_rotate(self, instance):
with self.lbl.canvas.before:
PushMatrix()
rotate = Rotate(angle=45)
with self.lbl.canvas.after:
PopMatrix()
rotate.origin = self.lbl.center
def update_scale(self, instance):
with self.btn.canvas.before:
PushMatrix()
s = Scale(2, 2, 1)
with self.btn.canvas.after:
PopMatrix()
s.origin = self.btn.center
def build(self):
root = FloatLayout()
self.lbl = Label(
text='Hello World', font_size=24,
halign='center', size_hint=(.2, .1),
pos=(300, 250)
)
with self.lbl.canvas:
Color(0, 1, 0, 0.25)
Rectangle(pos=self.lbl.pos, size=(200, 50))
self.btn = Button(
text='Rotate', size_hint=(None, None),
pos_hint={'center_x': .3, 'center_y': .1}
)
root.add_widget(self.lbl)
self.btn1 = Button(
text='Scale', size_hint=(None, None),
pos_hint={'center_x': .6, 'center_y': .1}
)
self.btn.bind(on_press=self.update_rotate)
self.btn1.bind(on_press=self.update_scale)
root.add_widget(self.btn)
root.add_widget(self.btn1)
return root
RotationApp().run()