Kivy 简明教程
Kivy - Canvas
与一些其他 GUI 工具包(例如 TKinter)不同,Kivy 没有独立的 Canvas 小组件。相反,您需要使用 Kivy 中每个 Widget 默认已有的画布。创建小组件时,您可以创建所有必要的指令以便绘制它的画布。
我们需要注意,所有小组件具有不同的画布,但所有画布都完全按照相同的绘图空间(即坐标空间)进行绘制。此外,绘图空间不受小组件的位置和大小的限制。绘图空间的 (0,0) 始终是左下角。
“canvas.before”属性在需要操作实例的颜色时特别有用。另一方面,canvas.after 用于在添加子项后执行任何指令。它在遍历所有子项后调用。
在 Kivy 中,Canvas 是绘图指令的集合。要进行绘制,您将需要一个 Canvas 对象和 Instruction 对象。例如,要在标签的画布上绘制一个矩形 -
from kivy.graphics import *
with label.canvas:
Color(1., 0, 0) # Add a red color
# Add a rectangle
Rectangle(pos=(10, 10), size=(500, 500))
如果您必须不使用 Python 的上下文管理器完成相同操作 -
label.canvas.add(Color(1., 0, 0))
label.canvas.add(Rectangle(size=(500, 500)))
您可以在任何小组件的画布上绘制形状,例如矩形、椭圆、线和贝塞尔曲线,包括 Widget 对象本身。(Widget 类是 Kivy 中所有其他可视化小组件的基础)
要在画布上绘制矩形,我们需要指定 pos 和 size 属性 -
from kivy.graphics import Rectangle
Rectangle(**kwargs)
Parameters
-
pos - X 和 Y 坐标值的列表,以 (x, y) 的格式指定矩形的位置。
-
size – 指定矩形的宽度和高度,格式为(宽度,高度)。
以下代码在 Widget 对象的画布上绘制一个矩形 –
widget=Widget()
with widget.canvas:
Color(0,0,1,1)
Rectangle(pos=(50,300), size_hint=(None, None), size=(300,200))
Color 和 Rectangle 指令自动添加到画布对象,并在绘制窗口时使用。
Syntax
您可能想使用“kv”语言语法 –
Widget:
canvas:
color:
rgb: 0,0,1
Rectangle:
pos: self.pos
size: self.size
Kivy 中的标签对象没有背景颜色属性。为了解决这个问题,您可以在其画布上绘制一个填充有所需颜色的矩形来提供背景。
lbl = Label(text='Hello World', font_size=24)
with lbl.canvas.before:
Color(1,1,0)
Rectangle(pos=lbl.pos, size=lbl.size)
或者,使用“kv”脚本 –
Label:
text:'Hello World'
font_size:24
canvas.before:
Color:
rgb: (1,1,0)
Rectangle:
pos:self.pos
size=:self.size
Parameters
-
segments – 定义绘制椭圆所需的线段数。线段越多,绘制出来的椭圆会更平滑,但如果您有许多线段,可能会减慢绘制速度。
-
angle_start – float,默认为 0.0,指定圆盘部分的起始角度(以度为单位)。
-
angle_end – float,默认为 360.0,指定圆盘部分的结束角度(以度为单位)。
-
angle_end – 椭圆的结束角度(以度为单位),默认为 360。
-
angle_start – 椭圆的起始角度(以度为单位),默认为 0。
-
pos – 画布坐标系中的位置
-
size – 椭圆的 X 和 Y 半径。如果两者相等,则变成一个圆。
您还可以在画布上直接绘制图像,方法是将图像文件指定为矩形或椭圆的源属性。
Example 1
以下代码实现了上面解释的所有绘制指令,以在小组件画布上显示矩形、椭圆和图像。它还放置了一个标签,标签包含一个在画布上绘制了背景色的矩形。
from kivy.app import App
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.graphics import *
from kivy.core.window import Window
Window.size = (720,400)
class canvasdemoapp(App):
def build(self):
widget=Widget()
# rectangle on canvas
with widget.canvas:
Color(0,0,1,1)
Rectangle(
pos=(50,300), size_hint=(None, None),
size=(300,200)
)
Color(0.5, .2, 0.4, 1)
d = 100
# ellipse
Ellipse(pos=(600,100), size=(d+75, d))
Color(.5,.5,.5)
# image
Rectangle(source='kivy-logo.png', pos=(50,100))
Color(1,1,1)
Rectangle(source='TPlogo.png', pos=(300, 100))
# label with background
lbl = Label(
text='Hello World', font_size=24,
pos=(Window.width/2, 300), size =(200,200),
color=(0,0,1,1)
)
with lbl.canvas.before:
Color(1,1,0)
Rectangle(pos=lbl.pos, size=lbl.size)
widget.add_widget(lbl)
btn=Button(
text='Button', font_size=24,
background_color= (.8, .4, .3, 1),
pos=(500,10)
)
widget.add_widget(btn)
return widget
canvasdemoapp().run()
Example 2
Widget 对象响应所有触摸事件(例如 on_touch_down 和 on_touch_move 等)。
在下面的示例中,Widget 对象上的 on_touch_down 事件的回调获取发生触摸事件的坐标,并绘制一个圆(X 和 Y 半径相等的椭圆),其中 RGB 颜色具有随机值。
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import *
import random
from kivy.core.window import Window
Window.size = (720,300)
class widget(Widget):
def on_touch_down(self, touch):
colorR = random.randint(0, 255)
colorG = random.randint(0, 255)
colorB = random.randint(0, 255)
self.canvas.add(Color(
rgb=(colorR / 255.0, colorG / 255.0, colorB / 255.0)
))
d = 30
self.canvas.add(Ellipse(
pos=(touch.x - d / 2, touch.y - d / 2),
size=(d, d)
))
class circlesapp(App):
def build(self):
return widget()
circlesapp().run()