画布 Canvas
Canvas是一种使用一组基本图形或"形状"(如线条、弧线、路径和文本)来绘制任意图形的控件。
示例
基本用法

import math
import flet as ft
import flet.canvas as cv
def main(page: ft.Page):
stroke_paint = ft.Paint(stroke_width=2, style=ft.PaintingStyle.STROKE)
fill_paint = ft.Paint(style=ft.PaintingStyle.FILL)
cp = cv.Canvas(
[
cv.Circle(100, 100, 50, stroke_paint),
cv.Circle(80, 90, 10, stroke_paint),
cv.Circle(84, 87, 5, fill_paint),
cv.Circle(120, 90, 10, stroke_paint),
cv.Circle(124, 87, 5, fill_paint),
cv.Arc(70, 95, 60, 40, 0, math.pi, paint=stroke_paint),
],
width=float("inf"),
expand=True,
)
page.add(cp)
ft.app(main)
Path
形状示例

import math
import flet as ft
import flet.canvas as cv
def main(page: ft.Page):
cp = cv.Canvas(
[
cv.Path(
[
cv.Path.MoveTo(25, 25),
cv.Path.LineTo(105, 25),
cv.Path.LineTo(25, 105),
],
paint=ft.Paint(
style=ft.PaintingStyle.FILL,
),
),
cv.Path(
[
cv.Path.MoveTo(125, 125),
cv.Path.LineTo(125, 45),
cv.Path.LineTo(45, 125),
cv.Path.Close(),
],
paint=ft.Paint(
stroke_width=2,
style=ft.PaintingStyle.STROKE,
),
),
],
width=float("inf"),
expand=True,
)
page.add(cp)
ft.app(main)
贝塞尔曲线

import math
import flet as ft
import flet.canvas as cv
def main(page: ft.Page):
cp = cv.Canvas(
[
cv.Path(
[
cv.Path.MoveTo(75, 25),
cv.Path.QuadraticTo(25, 25, 25, 62.5),
cv.Path.QuadraticTo(25, 100, 50, 100),
cv.Path.QuadraticTo(50, 120, 30, 125),
cv.Path.QuadraticTo(60, 120, 65, 100),
cv.Path.QuadraticTo(125, 100, 125, 62.5),
cv.Path.QuadraticTo(125, 25, 75, 25),
],
paint=ft.Paint(
stroke_width=2,
style=ft.PaintingStyle.STROKE,
),
),
cv.Path(
[
cv.Path.SubPath(
[
cv.Path.MoveTo(75, 40),
cv.Path.CubicTo(75, 37, 70, 25, 50, 25),
cv.Path.CubicTo(20, 25, 20, 62.5, 20, 62.5),
cv.Path.CubicTo(20, 80, 40, 102, 75, 120),
cv.Path.CubicTo(110, 102, 130, 80, 130, 62.5),
cv.Path.CubicTo(130, 62.5, 130, 25, 100, 25),
cv.Path.CubicTo(85, 25, 75, 37, 75, 40),
],
100,
100,
)
],
paint=ft.Paint(
gradient=ft.PaintRadialGradient(
ft.Offset(150, 150), 50, [ft.colors.PINK_100, ft.colors.PINK]
),
style=ft.PaintingStyle.FILL,
),
),
],
width=float("inf"),
expand=True,
)
page.add(cp)
ft.app(main)
绘制文本

import math
import flet as ft
import flet.canvas as cv
def main(page: ft.Page):
cp = cv.Canvas(
[
cv.Text(0, 0, "Just a text"),
cv.Circle(200, 100, 2, ft.Paint(color=ft.colors.RED)),
cv.Text(
200,
100,
"Rotated",
ft.TextStyle(weight=ft.FontWeight.BOLD, size=30),
spans=[
ft.TextSpan(
"around top_center",
ft.TextStyle(italic=True, color=ft.colors.GREEN, size=20),
)
],
alignment=ft.alignment.top_center,
rotate=math.pi * 0.15,
),
cv.Circle(400, 100, 2, ft.Paint(color=ft.colors.RED)),
cv.Text(
400,
100,
"Rotated around top_left",
ft.TextStyle(size=20),
alignment=ft.alignment.top_left,
rotate=math.pi * -0.15,
),
cv.Circle(600, 200, 2, ft.Paint(color=ft.colors.RED)),
cv.Text(
600,
200,
"Rotated around center",
ft.TextStyle(size=20),
alignment=ft.alignment.center,
rotate=math.pi / 2,
),
cv.Text(
300,
400,
"Limited to max_width and right-aligned.\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
text_align=ft.TextAlign.RIGHT,
max_width=400,
),
cv.Text(
200,
200,
"WOW!",
ft.TextStyle(
weight=ft.FontWeight.BOLD,
size=100,
foreground=ft.Paint(
gradient=ft.PaintLinearGradient(
(200, 200),
(300, 300),
colors=[ft.colors.YELLOW, ft.colors.RED],
),
stroke_join=ft.StrokeJoin.ROUND,
stroke_cap=ft.StrokeCap.ROUND,
),
),
),
cv.Text(
200,
200,
"WOW!",
ft.TextStyle(
weight=ft.FontWeight.BOLD,
size=100,
foreground=ft.Paint(
color=ft.colors.PINK,
stroke_width=6,
style=ft.PaintingStyle.STROKE,
stroke_join=ft.StrokeJoin.ROUND,
stroke_cap=ft.StrokeCap.ROUND,
),
),
),
],
width=float("inf"),
expand=True,
)
page.add(cp)
ft.app(main)
自由绘图工具 - 带手势检测的画布

import flet as ft
import flet.canvas as cv
class State:
x: float
y: float
state = State()
def main(page: ft.Page):
page.title = "Flet Brush"
def pan_start(e: ft.DragStartEvent):
state.x = e.local_x
state.y = e.local_y
def pan_update(e: ft.DragUpdateEvent):
cp.shapes.append(
cv.Line(
state.x, state.y, e.local_x, e.local_y, paint=ft.Paint(stroke_width=3)
)
)
cp.update()
state.x = e.local_x
state.y = e.local_y
cp = cv.Canvas(
[
cv.Fill(
ft.Paint(
gradient=ft.PaintLinearGradient(
(0, 0), (600, 600), colors=[ft.colors.CYAN_50, ft.colors.GREY]
)
)
),
],
content=ft.GestureDetector(
on_pan_start=pan_start,
on_pan_update=pan_update,
drag_interval=10,
),
expand=False,
)
page.add(
ft.Container(
cp,
border_radius=5,
width=float("inf"),
expand=True,
)
)
ft.app(main)
Canvas
属性
resize_interval
on_resize
事件的采样间隔,以毫秒为单位。默认值为0
,即在每次更改时调用on_resize
。
shapes
要绘制在画布上的Shape
对象(详见下文)的列表。
Canvas
事件
on_resize
当画布的大小发生变化时触发。
事件对象e
是CanvasResizeEvent
类的实例,具有以下字段:
width
- 画布的新宽度。height
- 画布的新高度。
Arc
形状属性
绘制一个按比例缩放以适应给定矩形的弧。
它从椭圆的start_angle
弧度开始,绕椭圆绕start_angle
+ sweep_angle
弧度,其中零弧度是椭圆右侧与通过矩形中心的水平线相交的点,正角度顺时针绕椭圆。如果use_center
为True
,则弧段闭合回中心,形成一个圆扇区。否则,弧段不闭合,形成一个圆段。
[图片] - https://api.flutter.dev/flutter/dart-ui/Canvas/drawArc.html
x
弧的左上角点的x轴坐标。
y
弧的左上角点的y轴坐标。
width
包含弧的椭圆的矩形的宽度。
height
包含弧的椭圆的矩形的高度。
start_angle
从哪个角度开始绘制弧。
sweep_angle
弧的长度(弧度)。
use_center
如果use_center
为True
,则弧段闭合回中心,形成一个圆扇区。否则,弧段不闭合,形成一个圆段。
paint
用于绘制弧的样式。该属性的值是ft.Paint
的实例。
Circle
形状属性
绘制一个圆。
x
圆心点的x轴坐标。
y
圆心点的y轴坐标。
radius
圆的半径。
paint
用于绘制圆的样式。该属性的值是ft.Paint
的实例。
Color
形状属性
将给定的color
绘制到画布上,应用给定的blend_mode
,其中给定的颜色是源,背景是目标。
color
要绘制到画布上的颜色。
blend_mode
要应用的混合模式。
请参阅ShaderMask.blend_mode
以获取可能的混合模式值。
Fill
形状属性
使用给定的Paint
填充画布。
要使用纯色和混合模式填充画布,请考虑使用Color
形状。
paint
用于填充画布的样式。该属性的值是ft.Paint
的实例。
Line
形状属性
使用给定的画笔在给定的点之间绘制一条线。该线是描边的,忽略Paint.style
的值。
x1
线的起点的x轴坐标。
y1
线的起点的y轴坐标。
x2
线的终点的x轴坐标。
y2
线的终点的y轴坐标。
paint
用于绘制线条的样式。该属性的值是ft.Paint
的实例。
Oval
形状属性
使用给定的Paint
绘制填充给定矩形的轴对齐椭圆。填充或描边(或两者)的方式由Paint.style
控制。
x
椭圆的左上角点的x轴坐标。
y
椭圆的左上角点的y轴坐标。
width
包含椭圆的矩形的宽度。
height
包含椭圆的矩形的高度。
paint
用于绘制椭圆的样式。该属性的值是 ft.Paint
的实例。
Path
形状属性
使用给定的 paint
绘制路径。
路径的填充或描边(或两者)由 Paint.style
控制。如果路径被填充,那么其中的子路径会被隐式关闭(参见 Path.Close
)。
elements
路径元素的列表:
Path.MoveTo(x, y)
从给定点(x
,y
)开始一个新的子路径。
Path.LineTo(x, y)
从当前点到给定点(x
,y
)添加一条直线段。
Path.QuadraticTo(cp1x, cp2y, x, y, w)
添加一个贝塞尔曲线段,它从当前点到给定点(x
,y
)曲线,使用控制点 (cp1x
,cp1y
) 和权重 w
。如果权重大于 1,那么曲线是一个双曲线;如果权重等于 1,则是一个抛物线;如果小于 1,则是一个椭圆。
Path.CubicTo(cp1x, cp1y, cp2x, cp2y, x, y)
添加一个立方贝塞尔曲线段,它从当前点到给定点(x
,y
)曲线,使用控制点 (cp1x
,cp1y
) 和 (cp2x
,cp2y
)。
Path.SubPath(elements, x, y)
将由 elements
描述的子路径添加到给定点(x
,y
)。
Path.Arc(x, y, width, height, start_angle, sweep_angle)
添加一个新的子路径,其中包含一段弧,该弧沿着以 x
和 y
为左上角,并具有 width
和 height
维度的矩形的边界。弧从椭圆开始的 start_angle
弧度开始,绕着椭圆一直到 start_angle + sweep_angle
弧度结束,其中 0 弧度是椭圆右侧交叉矩形中心的水平线上的点,正角度按顺时针方向绕椭圆。
Path.ArcTo(x, y, radius, rotation, large_arc, clockwise)
附加最多四个权重,以描述具有 radius
的椭圆,并且被 rotation
(以度为单位,顺时针)旋转。
第一个曲线从路径中的最后一个点开始,最后一个点在路径结束于 x
和 y
之前。曲线根据 clockwise
(布尔值)和 large_arc
(布尔值)决定路径方向,以使扫描角度始终小于 360 度。
如果任一半径为零或路径的最后一个点(x
,y
),则附加一个简单的线。如果两个都大于零但太小而无法描述弧,则将半径缩放以适应最后的路径点。
Path.Oval(x, y, width, height)
添加一个新的子路径,该路径由填充给定矩形的椭圆形成。
Path.Rect(x, y, width, height, border_radius)
将矩形添加为新的子路径。
Path.Close
关闭最后的子路径,就像从当前点到子路径的第一个点画一条直线一样。
paint
用于绘制路径的样式。该属性的值是 ft.Paint
的实例。
Points
形状属性
根据给定的 point_mode
绘制一系列点。
points
描述点的 ft.Offset
列表。
point_mode
在绘制一组点时如何解释点列表。值的类型为 ft.PointMode
:
POINTS
- 将每个点分开绘制。如果Paint.stroke_cap
是StrokeCap.ROUND
,那么每个点将以Paint.stroke_width
的直径绘制为圆,填充如Paint
描述的(忽略Paint.style
)。否则,每个点将绘制为边长为Paint.stroke_width
的轴对齐正方形,填充如Paint
描述的(忽略Paint.style
)。LINES
- 将每个两个点的序列绘制为线段。如果点数为奇数,则最后一个点将被忽略。线段将如Paint
描述的绘制(忽略Paint.style
)。POLYGON
- 将点序列绘制为一条线。线段将如Paint
描述的绘制(忽略Paint.style
)。
paint
用于绘制点的样式。该属性的值是 ft.Paint
的实例。
Rect
形状属性
绘制一个矩形。
x
矩形左上角的 x 轴坐标。
y
矩形左上角的 y 轴坐标。
width
矩形的宽度。
height
矩形的高度。
border_radius
矩形的边框半径,类型为 ft.BorderRadius
。
paint
用于绘制矩形的样式。该属性的值是 ft.Paint
的实例。
Shadow
形状属性
为表示给定材质 elevation
的 path
绘制阴影。
如果遮挡对象不是不透明的,则 transparent_occluder
参数应为 True
。
path
描述路径的 Path.PathElement
对象列表。
color
阴影
的颜色。
elevation
阴影的高程。
transparent_occluder
如果遮挡对象不是不透明的,则为 True
。默认为 False
。
Text
形状属性
在给定点 (x
, y
) 用 style
绘制 text
。
x
文本的 alignment
点的 x 轴坐标。
y
文本的 alignment
点的 y 轴坐标。
text
要绘制的文本。
style
用于绘制 text
和 spans
的文本样式。该值是 ft.TextStyle
类的实例。
spans
用于构建富文本段落的 ft.TextSpan
对象列表。
alignment
确定文本矩形的位置和旋转中心的点。
值的类型为 ft.Alignment
。默认值为 ft.alignment.top_left
。
text_align
文本水平对齐方式。支持的值请参见 Text.text_align
属性。
max_lines
要绘制的最大行数。超过此数的行将被忽略。例如,如果 max_lines
为 1,则只绘制一行。如果 max_lines
为 None
,但省略号不为 None
,则超出宽度约束的第一行之后的行将被忽略。
max_width
绘制文本的最大宽度。默认值为 None
- 无限。
ellipsis
用于省略溢出文本的字符串。
rotate
以弧度为单位的文本旋转。文本围绕由 alignment
确定的点旋转。请参阅上面的代码示例。
Paint
属性
在画布上绘制形状时要使用的样式描述。
anti_alias
是否对画布上绘制的线条和图像应用抗锯齿。默认为 True
。
blend_mode
该属性尚未实现,保留供将来使用。
绘制形状或合成图层时应用的混合模式。
默认为 BlendMode.SRC_OVER
。
请参阅 ShaderMask.blend_mode
以获取可能的混合模式值。
blur_image
该属性尚未实现,保留供将来使用。
在画布上绘制图像时进行模糊处理。
有关更多信息,请参阅 Container.blur
。
color
在绘制形状的填充或描边时要使用的颜色。默认为不透明的黑色。
gradient
配置渐变填充。其值是以下类之一的实例:
PaintLinearGradient
PaintRadialGradient
PaintSweepGradient
Path
形状属性
PaintLinearGradient

cv.Rect(
10,
10,
100,
100,
5,
ft.Paint(
gradient=ft.PaintLinearGradient(
(0, 10), (0, 100), colors=[ft.colors.BLUE, ft.colors.YELLOW]
),
style=ft.PaintingStyle.FILL,
),
)
PaintLinearGradient
类具有以下属性:
begin
-Offset
类的实例。渐变的起始位置。end
-Offset
类的实例。渐变的结束位置。colors
- 渐变在每个位置应该具有的颜色。如果stops
参数为非空,则该列表的长度必须与stops
参数的长度相同。该列表至少必须包含两种颜色(否则,它不是渐变!)。stops
- 一个从0.0到1.0的值的列表,表示沿着渐变的分数位置。如果stops
参数为非空,则该列表的长度必须与colors
参数的长度相同。如果第一个值不是0.0,则会隐含一个位置为0.0且颜色为colors
列表中的第一个颜色的停止点。如果最后一个值不是1.0,则会隐含一个位置为1.0且颜色为colors
列表中的最后一个颜色的停止点。tile_mode
- 渐变在begin
和end
之前和之后的平面上如何平铺。该值是GradientTileMode
枚举,支持的值有:CLAMP
(默认值)、DECAL
、MIRROR
、REPEATED
。更多信息请参阅这里。rotation
- 渐变的旋转角度,以渐变边界框的中心点为中心点,单位为弧度。
更多信息:
- 在Flutter文档中的线性渐变。
- Radian measuring unit on Wikipedia.
PaintRadialGradient

cv.Circle(
60,
170,
50,
ft.Paint(
gradient=ft.PaintRadialGradient(
(60, 170), 50, colors=[ft.colors.YELLOW, ft.colors.BLUE]
),
style=ft.PaintingStyle.FILL,
),
)
PaintRadialGradient
类具有以下属性:
center
-Offset
类的实例。渐变的中心位置。radius
- 渐变的半径。colors
、stops
、tile_mode
、rotation
- 参见线性渐变中对这些属性的描述。focal
- 渐变的焦点。如果指定了焦点,则渐变将沿着从center
到焦点的向量聚焦。focal_radius
- 渐变焦点的半径,作为绘制框最短边的一部分。例如,如果在宽度为100.0像素、高度为200.0像素的框上绘制径向渐变,则半径为1.0将使1.0的停止点距离焦点100.0像素。
更多信息:
- 在Flutter文档中的径向渐变。
PaintSweepGradient

cv.Path(
[
cv.Path.MoveTo(60, 230),
cv.Path.LineTo(110, 330),
cv.Path.LineTo(10, 330),
cv.Path.Close(),
],
ft.Paint(
gradient=ft.PaintSweepGradient(
(60, 280),
colors=[ft.colors.YELLOW, ft.colors.BLUE],
start_angle=0,
end_angle=math.pi * 2,
),
stroke_width=5,
stroke_join=ft.StrokeJoin.ROUND,
style=ft.PaintingStyle.STROKE,
),
)
PaintSweepGradient
类具有以下属性:
center
- 渐变的中心位置。colors
、stops
、tile_mode
、rotation
- 参见线性渐变中对这些属性的描述。start_angle
- 渐变的起始角度(以弧度为单位)。默认值为0.0。end_angle
- 渐变的结束角度(以弧度为单位)。默认值为math.pi * 2。rotation
- 渐变的旋转角度(以弧度为单位)。
更多信息:
- 在Flutter文档中的扫描渐变。
stroke_cap
当style
设置为PaintingStyle.STROKE
时,线段末端的样式。
该值是ft.StrokeCap
枚举的一个实例:
BUTT
(默认值)- 线段的末端以平直的边缘结束,没有延伸。ROUND
- 线段的末端以半圆形的延伸结束。SQUARE
- 线段的末端以半个正方形的延伸结束。这类似于将每个线段的末端延长半个线段宽度(由Paint.stroke_width
给定)。
stroke_join
线段之间连接的样式。
这适用于style
设置为PaintingStyle.STROKE
时绘制的路径,不适用于使用canvas.Points
绘制的点线。
默认值为StrokeJoin.MITER
,即尖锐的拐角。
该值是ft.StrokeJoin
枚举的一个实例:
MITER
(默认值)- 线段之间的连接形成尖锐的拐角。ROUND
- 线段之间的连接是半圆形的。BEVEL
- 线段之间的连接将线段的末端的角连接起来,形成斜角外观。
有关详细信息,请参阅Flutter文档中的StrokeJoin枚举。
stroke_miter_limit
当连接设置为StrokeJoin.MITER
且样式设置为PaintingStyle.STROKE
时,线段上的斜接限制。如果超过此限制,则将绘制StrokeJoin.BEVEL
连接。如果线段之间的角度发生动画变化,这可能会导致路径的角出现一些"弹跳"效果。
该限制表示为斜接的长度限制。
默认值为4.0。将限制设置为0将始终使用StrokeJoin.BEVEL
连接。
stroke_width
当样式设置为PaintingStyle.STROKE
时,边缘的宽度。宽度以与路径方向垂直的逻辑像素为单位。
默认值为0.0,对应于毛细线宽度。
stroke_dash_pattern
虚线的偏移和长度的循环数组。
例如,数组[5, 10]
将生成长度为5像素的虚线,后面跟着长度为10像素的空白间隔。数组[5, 10, 5]
将生成长度为5像素的虚线,后面跟着长度为10像素的空白间隔,再后面是长度为5像素的虚线,以此类推。
style
绘制形状的内部、边缘或两者。
该值是ft.PaintingStyle
枚举的一个实例:
FILL
(默认值)- 将Paint
应用于形状的内部。例如,应用于canvas.Circle
形状时,将绘制一个给定大小的圆盘。STROKE
- 将Paint
应用于形状的边缘。例如,应用于canvas.Circle
形状时,将绘制一个给定大小的圆环。边缘上绘制的线的宽度由Paint.stroke_width
属性给定。