Qt6 Quick项目Canvas绘制

前言

本文主要说在QML中怎样使用Canvas绘制图片。

绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 1. 定义Canvas元素
Canvas {
id: canvas
width: container.width
height: container.height

// 2. 获取2D绘图上下文(全局变量,方便调用)
property var ctx: null

Component.onCompleted: {
// 初始触发一次绘制,用于获取上下文
// requestPaint()
loadImage("qrc:/images/logo01.png");
}

// 3. 绘图逻辑(onPaint信号触发时执行)
onPaint: {
if (!ctx) {
ctx = getContext("2d")
if (!ctx) {
console.error("获取Canvas上下文失败!")
return
}
}
// 清除画布(可选,避免重绘时叠加)
ctx.clearRect(0, 0, width, height)

// ===== 绘制矩形 =====
ctx.fillStyle = "rgba(255, 0, 0, 0.5)" // 半透明红色填充
ctx.strokeStyle = "blue" // 蓝色边框
ctx.lineWidth = 3 // 边框宽度
ctx.fillRect(50, 50, 200, 100) // 填充矩形(x, y, w, h)
ctx.strokeRect(50, 50, 200, 100) // 描边矩形

// ===== 绘制圆形(使用路径)=====
ctx.beginPath() // 开始路径
ctx.arc(400, 125, 75, 0, Math.PI * 2) // 圆心(400,125),半径75,0到360度
ctx.fillStyle = "transparent" // 无填充
ctx.strokeStyle = "green" // 绿色边框
ctx.lineWidth = 2
ctx.stroke() // 描边路径

// ===== 绘制文本 =====
ctx.font = "bold 16px 'SimHei'" // 字体(支持中文需指定中文字体)
ctx.fillStyle = "black" // 文本颜色
ctx.fillText("你好!", 40, 180) // 绘制文本(内容, x, y)

// ===== 绘制图像 =====
ctx.drawImage("qrc:/images/logo01.png",50, 200, 46, 46)

}
}

绘制矩形

1
2
3
4
5
6
// ===== 绘制矩形 =====
ctx.fillStyle = "rgba(255, 0, 0, 0.5)" // 半透明红色填充
ctx.strokeStyle = "blue" // 蓝色边框
ctx.lineWidth = 3 // 边框宽度
ctx.fillRect(50, 50, 200, 100) // 填充矩形(x, y, w, h)
ctx.strokeRect(50, 50, 200, 100) // 描边矩形

绘制圆形

1
2
3
4
5
6
7
// ===== 绘制圆形(使用路径)=====
ctx.beginPath() // 开始路径
ctx.arc(400, 125, 75, 0, Math.PI * 2) // 圆心(400,125),半径75,0到360度
ctx.fillStyle = "transparent" // 无填充
ctx.strokeStyle = "green" // 绿色边框
ctx.lineWidth = 2
ctx.stroke() // 描边路径

绘制文字

1
2
3
4
// ===== 绘制文本 =====
ctx.font = "bold 16px 'SimHei'" // 字体(支持中文需指定中文字体)
ctx.fillStyle = "black" // 文本颜色
ctx.fillText("你好!", 40, 180) // 绘制文本(内容, x, y)

绘制图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 1. 定义Canvas元素
Canvas {
id: canvas
width: container.width
height: container.height

// 2. 获取2D绘图上下文(全局变量,方便调用)
property var ctx: null

Component.onCompleted: {
loadImage("qrc:/images/logo01.png");
}

// 3. 绘图逻辑(onPaint信号触发时执行)
onPaint: {
if (!ctx) {
ctx = getContext("2d")
if (!ctx) {
console.error("获取Canvas上下文失败!")
return
}
}
// 清除画布(可选,避免重绘时叠加)
ctx.clearRect(0, 0, width, height)
// ===== 绘制图像 =====
ctx.drawImage("qrc:/images/logo01.png",50, 200, 46, 46)

}
}

注意要loadImage

笔迹绘制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// 1. 定义Canvas元素
Canvas {
id: canvas
width: container.width
height: container.height

// 2. 获取2D绘图上下文(全局变量,方便调用)
property var ctx: null

property var pathList: []
property bool isDrawing: false // 是否正在绘制

Component.onCompleted: {

loadImage("qrc:/images/logo01.png")
}

// 3. 绘图逻辑(onPaint信号触发时执行)
onPaint: {
if (!ctx) {
ctx = getContext("2d")
if (!ctx) {
console.error("获取Canvas上下文失败!")
return
}
}
// 清除画布(可选,避免重绘时叠加)
ctx.clearRect(0, 0, width, height)

// 初始化画笔样式
ctx.lineWidth = 3 // 线宽
ctx.strokeStyle = "red" // 线条颜色
ctx.lineCap = "round" // 线帽(圆角)
ctx.lineJoin = "round" // 线连接(圆角)

// 如果有路径点,绘制路径
if (pathList.length > 0) {
for (var i = 0; i < pathList.length; i++) {
let pointList = pathList[i]
ctx.beginPath()
// 移动到第一个点(起始点)
ctx.moveTo(pointList[0].x, pointList[0].y)
// 依次连接后续所有点
for (var j = 1; j < pointList.length; j++) {
ctx.lineTo(pointList[j].x, pointList[j].y)
}
ctx.stroke() // 描边路径
}
}
}

// 鼠标事件捕获(支持触摸时可替换为TouchArea)
MouseArea {
anchors.fill: parent
onPressed: {
// 按下时:开始新路径,记录第一个点
canvas.isDrawing = true
var arr = [{
"x": mouseX,
"y": mouseY
}]
canvas.pathList.push(arr)
canvas.requestPaint()
}
onPositionChanged: {
// 移动时:如果正在绘制,添加新点并重绘
if (canvas.isDrawing) {
var pointList = canvas.pathList[canvas.pathList.length - 1]
pointList.push({
"x": mouseX,
"y": mouseY
})
canvas.requestPaint()
}
}
onReleased: {
// 释放时:结束绘制
canvas.isDrawing = false
canvas.requestPaint()
}
}

// 清除按钮
Button {
text: "清除"
x: 20
y: 20
onClicked: {
canvas.pathList = [] // 清空路径点
canvas.requestPaint() // 重绘(清除画布)
}
}
}