Kivy - Canvas
与其他一些 GUI 工具包(例如 TKinter)不同,Kivy 没有独立的 Canvas 小部件。相反,您需要使用 Kivy 中每个小部件默认已有的画布。创建小部件时,您可以创建在其画布上绘图所需的所有指令。
我们需要注意,所有小部件都有不同的画布,但所有画布都在完全相同的绘图空间(即坐标空间)中绘制。此外,绘图空间不限于小部件的位置和大小。绘图空间的 (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)))
您可以在任何小部件的画布上绘制矩形、椭圆、直线和 Beizer 等形状,包括 Widget 对象本身。(Widget 类是 Kivy 中所有其他可视化小部件的基础)
要在画布上绘制矩形,我们需要指定 pos 和 size 属性 −
from kivy.graphics import Rectangle Rectangle(**kwargs)
参数
pos − 指定矩形位置的 X 和 Y 坐标值列表,格式为 (x, y)。
size − 指定矩形宽度和高度的列表,格式为 (width, height)。
以下代码在 Widget 对象的画布上绘制一个矩形 −
widget=Widget() with widget.canvas: Color(0,0,1,1) Rectangle(pos=(50,300), size_hint=(None, None), size=(300,200))
指令 Color 和 Rectangle 会自动添加到画布对象中,并在绘制窗口时使用。
语法
您可能希望使用"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)
Or, using the "kv" script −
Label: text:'Hello World' font_size:24 canvas.before: Color: rgb: (1,1,0) Rectangle: pos:self.pos size=:self.size
语法
您可以使用以下语法在画布上绘制椭圆 −
from kivy.graphics import Ellipse Ellipse(*args, **kwargs)
参数
segments − 定义绘制椭圆所需的段数。段数越多,绘制就越平滑。
angle_start − 浮点数,默认为 0.0,指定圆盘部分的起始角度(以度为单位)。
angle_end −浮点数,默认为 360.0,指定圆盘部分的结束角度(以度为单位)。
angle_end − 椭圆的结束角度(以度为单位),默认为 360。
angle_start − 椭圆的起始角度(以度为单位),默认为 0。
pos − 画布坐标系上的位置
size − 椭圆的 X 和 Y 半径。如果两者相等,则变成圆形。
您也可以直接在画布上绘制图像,方法是将图像文件指定为矩形或椭圆的源属性。
示例 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()
输出
运行此代码时,将产生以下输出 −
示例 2
Widget 对象响应所有触摸事件(例如 on_touch_down 和 on_touch_move 等)。
在下面的示例中,Widget 对象上的 on_touch_down 事件的回调获取触摸事件发生的坐标,并使用随机的 RGB 颜色值绘制一个圆(X 和 Y 半径相等的椭圆)。
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()
输出
运行程序并在不同位置生成 touch_down 事件。 圆圈将被绘制在位置。