画布元素(canvas element)的基本思想是使⽤⼀个2D对象来渲染路径。这个2D对象包括了必要的绘图函数,画布元素(canvas element)充当绘制画布。2D对象⽀持画笔,填充,渐变,⽂本和绘制路径创建命令。canvas项目允许绘制直线和曲线,简单和复杂的形状,图形以及参考的图形图像。它还可以添加文本,颜色,阴影,渐变和图案,并执行低级像素操作。canvas输出可以保存为图像文件或序列化为URL。
在QML中,画布元素(canvas element)充当了绘制的容器。2D绘制对象提供了实际绘制的⽅法。绘制需要在onPaint事件中完成以下代码创建一个Canvas项目,画一条直线。
典型绘制命令调⽤如下:
1. 装载画笔或者填充模式
2. 创建绘制路径
3. 使⽤画笔或者填充绘制路径
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Canvas {
id: mycanvas
width: 100
height: 200
onPaint: {
var ctx = getContext("2d");
// setup the stroke
ctx.strokeStyle = "red"
// create a path
ctx.beginPath()
ctx.moveTo(50,50)
ctx.lineTo(150,50)
// stroke path
ctx.stroke()
}
}
}
在绘制矩形时,我们提供了⼀个便捷的接⼝,而不需要调⽤stroke或者fill来完成。
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
//定位元素,画四个带颜色的正方形
Row {
id: colorTools
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 8
}
property color paintColor: "#33B5E5"
spacing: 4
//清楚按钮
Button {
text: "Clear"
onClicked: {
canvas.clear()
}
}
//绑定点击更换颜色
Repeater {
model: ["#33B5E5", "#99CC00", "#FFBB33", "#FF4444"]
Rectangle {
id: colorSquare;
width: 48; height: 48
color: modelData
signal clicked
property bool active: false
border.color: active? "#666666" : "#f0f0f0"
border.width: 2
MouseArea {
id: area1
anchors.fill :parent
onClicked: {
colorTools.paintColor = color
}
}
}
}
}
//画框
Rectangle{
anchors.fill: canvas
border.color: "#666"
border.width: 4;
}
Canvas {
id: canvas
anchors {
left: parent.left
right: parent.right
top: colorTools.bottom
bottom: parent.bottom
margins: 8
}
property real lastX
property real lastY
property color color: colorTools.paintColor //继承颜色
//清除函数
function clear() {
var ctx = getContext('2d')
ctx.reset();
canvas.requestPaint();
}
onPaint: {
var ctx = getContext('2d')
ctx.lineWidth = 1.5
ctx.strokeStyle = canvas.color
ctx.beginPath()
ctx.moveTo(lastX, lastY)
lastX = area.mouseX
lastY = area.mouseY
ctx.lineTo(lastX, lastY)
ctx.stroke()
}
MouseArea {
id: area
anchors.fill: parent
onPressed: {
canvas.lastX = mouseX
canvas.lastY = mouseY
}
onPositionChanged: {
canvas.requestPaint()
}
}
}
}
效果如下:
1. 在这个例⼦中我们将使⽤画布(Canvas)创建⼀个简单的鼠标绘制程序。
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window{
id: root
width: 640
height: 480
visible: true
//鼠标点击坐标位置
property real startX //储存鼠标开始时的坐标
property real startY
property real stopX //储存鼠标结束时的坐标
property real stopY
//在root上画一个方框
Rectangle{
anchors.fill: canvas
border.color: "#666"
border.width: 4;
}
//创建一个画布
Canvas{
id:canvas;
anchors.fill:parent
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 3
ctx.strokeStyle = "blue";
//开始绘制
ctx.beginPath()
ctx.moveTo(startX,startY)
//纪录鼠标开始的位置的坐标点
startX = area.mouseX;
startY = area.mouseY;
ctx.lineTo(startX,startY)
ctx.stroke()
}
}
MouseArea{
id:area;
anchors.fill: parent;
//当鼠标按下时调用本函数
onPressed: {
startX = mouse.x;
startY = mouse.y;
isMouseMoveEnable = true
}
//当鼠标释放时调用本函数
onReleased: {
isMouseMoveEnable = false
canvas.requestPaint() //当鼠标released时,调用绘制paint
}
//当鼠标press位置改变,调用本函数
onPositionChanged: {
if (isMouseMoveEnable){
canvas.requestPaint() //绘制函数
}
}
}
}
效果如下:
对上述例子进行扩展:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
Row {
id: colorTools
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 8
}
property color paintColor: "#33B5E5"
spacing: 4
Button {
text: "Clear"
onClicked: {
canvas.clear()
}
}
Repeater {
model: ["#33B5E5", "#99CC00", "#FFBB33", "#FF4444"]
Rectangle {
id: colorSquare;
width: 48; height: 48
color: modelData
signal clicked
property bool active: false
border.color: active? "#666666" : "#f0f0f0"
border.width: 2
MouseArea {
id: area1
anchors.fill :parent
onClicked: {
colorTools.paintColor = color
}
}
}
}
}
Rectangle{
anchors.fill: canvas
border.color: "#666"
border.width: 4;
}
Canvas {
id: canvas
anchors {
left: parent.left
right: parent.right
top: colorTools.bottom
bottom: parent.bottom
margins: 8
}
property real lastX
property real lastY
property color color: colorTools.paintColor
function clear() {
var ctx = getContext('2d')
ctx.reset();
canvas.requestPaint();
}
onPaint: {
var ctx = getContext('2d')
ctx.lineWidth = 1.5
ctx.strokeStyle = canvas.color
ctx.beginPath()
ctx.moveTo(lastX, lastY)
lastX = area.mouseX
lastY = area.mouseY
ctx.lineTo(lastX, lastY)
ctx.stroke()
}
MouseArea {
id: area
anchors.fill: parent
onPressed: {
canvas.lastX = mouseX
canvas.lastY = mouseY
}
onPositionChanged: {
canvas.requestPaint()
}
}
}
}
效果如下:
2. 鼠标绘制长方形,无绘制轨迹
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window{
id: root
width: 640
height: 480
visible: true
//鼠标点击坐标位置
property real startX //储存鼠标开始时的坐标
property real startY
property real stopX //储存鼠标结束时的坐标
property real stopY
property bool isMouseMoveEnable: false //是否允许鼠标移动绘制事件
//在root上画一个方框
Rectangle{
anchors.fill: canvas
border.color: "#666"
border.width: 4;
}
//创建一个画布
Canvas{
id:canvas;
anchors.fill:parent
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 3
ctx.strokeStyle = "blue";
if (!isMouseMoveEnable) {
ctx.clearRect(0,0,width,height) //清空所画图形
return;
}
if (isMouseMoveEnable){
ctx.clearRect(0,0,width,height)
}
//开始绘制
ctx.beginPath()
ctx.moveTo(startX,startY)
//记录移动终点
stopX = area.mouseX
stopY = area.mouseY
//绘制长方形
ctx.strokeRect(startX,startY,stopX-startX,stopY-startY)
ctx.stroke()
}
}
MouseArea{
id:area;
anchors.fill: parent;
//当鼠标按下时调用本函数
onPressed: {
startX = mouse.x;
startY = mouse.y;
isMouseMoveEnable = true
}
//当鼠标press位置改变,调用本函数
onPositionChanged: {
if (isMouseMoveEnable){
canvas.requestPaint() //绘制函数
}
}
}
}
效果如下:
3. 鼠标释放长方形消失
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window{
id: root
width: 640
height: 480
visible: true
//鼠标点击坐标位置
property real startX //储存鼠标开始时的坐标
property real startY
property real stopX //储存鼠标结束时的坐标
property real stopY
property bool isMouseMoveEnable: false //是否允许鼠标移动绘制事件
//在root上画一个方框
Rectangle{
anchors.fill: canvas
border.color: "#666"
border.width: 4;
}
//创建一个画布
Canvas{
id:canvas;
anchors.fill:parent
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 3
ctx.strokeStyle = "blue";
if (!isMouseMoveEnable) {
ctx.clearRect(0,0,width,height) //清空所画图形
return;
}
if (isMouseMoveEnable){
ctx.clearRect(0,0,width,height)
}
//开始绘制
ctx.beginPath()
ctx.moveTo(startX,startY)
//console.log(startX,startY)
//记录移动终点
stopX = area.mouseX
stopY = area.mouseY
//绘制长方形
ctx.strokeRect(startX,startY,stopX-startX,stopY-startY)
ctx.stroke()
}
}
MouseArea{
id:area;
anchors.fill: parent;
//当鼠标按下时调用本函数
onPressed: {
startX = mouse.x;
startY = mouse.y;
isMouseMoveEnable = true
}
//当鼠标释放时调用本函数
onReleased: {
isMouseMoveEnable = false
canvas.requestPaint() //当鼠标released时,调用绘制paint
}
//当鼠标press位置改变,调用本函数
onPositionChanged: {
if (isMouseMoveEnable){
canvas.requestPaint() //绘制函数
}
}
}
}
效果如下:
4. 有绘制轨迹的
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window{
id: root
width: 640
height: 480
visible: true
//鼠标点击坐标位置
property real startX //储存鼠标开始时的坐标
property real startY
property real stopX //储存鼠标结束时的坐标
property real stopY
property bool isMouseMoveEnable: false //是否允许鼠标移动绘制事件
//在root上画一个方框
Rectangle{
anchors.fill: canvas
border.color: "#666"
border.width: 4;
}
//创建一个画布
Canvas{
id:canvas;
anchors.fill:parent
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 3
ctx.strokeStyle = "blue";
//开始绘制
ctx.beginPath()
ctx.moveTo(startX,startY)
//console.log(startX,startY)
//记录移动终点
stopX = area.mouseX
stopY = area.mouseY
//绘制长方形
ctx.strokeRect(startX,startY,stopX-startX,stopY-startY)
ctx.stroke()
}
}
MouseArea{
id:area;
anchors.fill: parent;
//当鼠标按下时调用本函数
onPressed: {
startX = mouse.x;
startY = mouse.y;
isMouseMoveEnable = true
}
//当鼠标press位置改变,调用本函数
onPositionChanged: {
if (isMouseMoveEnable){
canvas.requestPaint() //绘制函数
}
}
}
}
效果如下:
扩展可以仿照前面的写,这里就不在叙述了。