gitHub:sueRimn
源码:
qml-draw-canvas (随笔画) qml-draw-canvs-press(按压随笔画)qml-draw-canvas-path(预览路径)
用纯qml实现canvas画板功能,用鼠标进行画图,可以画直线,画圆,画矩形,画弧线。
由于canvas画图会有延迟和卡顿,建议还是结合c++实现画图功能。
以下gif效果都没有录进鼠标
1.鼠标点击画图-无预览路径(两点实现)
贴上代码和注释:
property real startX
property real startY
property real stopX
property real stopY
property color color: colorTools.paintColor
property var paintType: ["line","rect","circle","curve"]//自定义绘制类型
property var clickPoint: []//多边形画图的存点数组 未实现
property int clickNum: 0//鼠标点击
Row{
id:colorTools//颜色提取工具
anchors{
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 8
}
property color paintColor: "#33b5e5"//设置初始画笔颜色
spacing: 4;
// Repeater{//四个colorSquare
// model: ["#33B5E5", "#99CC00", "#FFBB33", "#FF4444"]//modelData 颜色数据
// ColorSquare{
// id:red;
// color: modelData;
// active: parent.paintColor == color//当选中一个colorSquare时,当前画笔颜色为选中的颜色
// onClicked: {
// parent.paintColor = color
// }
// }
// }
Button {
text: "Clear"
onClicked: {
canvas.clear()
}
}
Button{
text: "line";
onClicked: {
paintType = "line";
//canvas.requestPaint();
}
}
Button{
text: "rect"
onClicked: {
paintType = "rect";
// canvas.requestPaint();
}
}
Button{
text: "circle"
onClicked: {
paintType = "circle";
// canvas.requestPaint();
}
}
Button{
text: "curve"
onClicked: {
paintType = "curve";
// canvas.requestPaint();
}
}
}
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
}
//鼠标点击坐标位置
function clear() {
var ctx = getContext("2d");
ctx.reset();
canvas.requestPaint();
}
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 5
ctx.strokeStyle = canvas.color;//轮廓颜色
//ctx.fillStyle = canvas.color;//填充颜色
ctx.beginPath()
if(paintType === "line"){
ctx.moveTo(startX,startY)
startX = area.mouseX;
startY = area.mouseY;
ctx.lineTo(stopX,stopY)
stopX = area.mouseX;
stopY = area.mouseY;
}
if(paintType === "rect"){
//ctx.fillRect(startX,startY,stopX-startX,stopY-startY)//填充类型
//ctx.clearRect(0,0,width,height)
ctx.strokeRect(startX,startY,stopX-startX,stopY-startY)//非填充
}
if(paintType === "circle"){
ctx.arc(startX,startY,Math.sqrt(Math.pow((stopX-startX),2)+Math.pow((stopY-startY),2)),0,360,false)
}
if(paintType === "curve"){
ctx.arcTo(startX,startY,stopX,stopY,Math.sqrt(Math.pow((stopX-startX),2)+Math.pow((stopY-startY),2)))
}
// ctx.fill();//完成填充
ctx.stroke()
}
MouseArea{
id:area;
anchors.fill: parent;
onClicked: {//存点 遍历
//clickPoint.push({"x":mouseX,"y":mouseY})//多边形绘制存点 多边形未实现
clickNum++;
for(var i = 0;i<clickPoint.length;i++){
var point = clickPoint[i];
}
if(clickNum == 1){
startX = mouseX;
startY = mouseY;
}
if(clickNum == 2){
clickNum = 0;
stopX = mouseX;
stopY = mouseY;
canvas.requestPaint();
}
}
}
}
}
2.鼠标按压拖动绘图-无预览路径(鼠标释放完成绘制)
代码和注释:
property real startX
property real startY
property real stopX
property real stopY
property color color: colorTools.paintColor
property var paintType: ["line","rect","circle","curve"]
property var clickPoint: []
property int clickNum: 0
Row{
id:colorTools//颜色提取工具
anchors{
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 8
}
property color paintColor: "#33b5e5"//设置初始画笔颜色
spacing: 4;
// Repeater{//四个colorSquare
// model: ["#33B5E5", "#99CC00", "#FFBB33", "#FF4444"]//modelData 颜色数据
// ColorSquare{
// id:red;
// color: modelData;
// active: parent.paintColor == color//当选中一个colorSquare时,当前画笔颜色为选中的颜色
// onClicked: {
// parent.paintColor = color
// }
// }
// }
Button {
text: "Clear"
onClicked: {
canvas.clear()
}
}
Button{
text: "line";
onClicked: {
paintType = "line";
//canvas.requestPaint();
}
}
Button{
text: "rect"
onClicked: {
paintType = "rect";
// canvas.requestPaint();
}
}
Button{
text: "circle"
onClicked: {
paintType = "circle";
// canvas.requestPaint();
}
}
Button{
text: "curve"
onClicked: {
paintType = "curve";
// canvas.requestPaint();
}
}
}
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
}
//鼠标点击坐标位置
function clear() {//此清除有问题
var ctx = getContext("2d");
ctx.reset();
canvas.requestPaint();
}
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 10
ctx.strokeStyle = canvas.color;
// ctx.fillStyle = canvas.color;//若想要填充的 此不注释
ctx.beginPath()
if(paintType === "line"){
ctx.moveTo(startX,startY)
startX = area.mouseX;
startY = area.mouseY;
ctx.lineTo(stopX,stopY)
stopX = area.mouseX;
stopY = area.mouseY;
}
if(paintType === "rect"){
//ctx.fillRect(startX,startY,stopX-startX,stopY-startY)//填充类型
//ctx.clearRect(0,0,width,height)
ctx.strokeRect(startX,startY,stopX-startX,stopY-startY)//非填充
}
if(paintType === "circle"){
ctx.arc(startX,startY,Math.sqrt(Math.pow((stopX-startX),2)+Math.pow((stopY-startY),2)),0,360,false)
}
if(paintType === "curve"){//未实现
ctx.arcTo(startX,startY,stopX,stopY,Math.sqrt(Math.pow((stopX-startX),2)+Math.pow((stopY-startY),2)))
}
//ctx.fill();
ctx.stroke()
}
MouseArea{
id:area;
anchors.fill: parent;
// onClicked: {//存点 遍历
// clickPoint.push({"x":mouseX,"y":mouseY})
// clickNum++;
// for(var i = 0;i<clickPoint.length;i++){
// var point = clickPoint[i];
// }
// if(clickNum == 1){
// startX = mouseX;
// startY = mouseY;
// }
// if(clickNum == 2){
// clickNum = 0;
// stopX = mouseX;
// stopY = mouseY;
// canvas.requestPaint();
// }
// }
onPressed: {
startX = mouseX;
startY = mouseY;
}
onMouseXChanged: {
stopX = mouseX;
}
onMouseYChanged: {
stopY = mouseY;
}
onReleased: {
canvas.requestPaint()//重绘
}
// onPositionChanged: {
// canvas.requestPaint()//重绘 这句话不注释 会有预览路径 但是临时区没有清理 需要在cpp中进行清除
// }
}
}
3.鼠标按压拖动绘制-有预览路径
因为想要绘制的过程中有预览路径,需要在cpp中实现清理临时区域,因为如果不清理 ,画直线的时候没问题,但是在画矩形圆的时候会出现如下情况:
cpp中如何画,可以参考这篇博文:https://blog.csdn.net/foruok/article/details/32698603
第三种方法可以在qml中有预览路径的同时也清理临时图区,只不过只能存在一个图元,也就是画了直线之后画圆,直线就会消失。所以还是建议结合c++中的QQuickPaintedItem方法等进行清理临时图区。这个链接有三个实例提供参考 https://www.aliyun.com/jiaocheng/173346.html ,上面那个链接就是对第一个实例的解释
以下代码我做了临时图元的简单清理,但是画线段的时候由于清理了,所以画不出来了,所以还是建议看博客结合cpp
通过gif可以看到录制把临时图元都看到了,但是在实际绘制的时候却看不到的,?
纯Qml代码如下:
property real startX
property real startY
property real stopX
property real stopY
property color color: colorTools.paintColor
property var paintType: ["line","rect","circle","curve"]
property bool isMouseMoveEnable: false //是否允许鼠标移动绘制事件
Row{
id:colorTools//颜色提取工具
anchors{
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 8
}
property color paintColor: "#33b5e5"//设置初始画笔颜色
spacing: 4;
// Repeater{//四个colorSquare
// model: ["#33B5E5", "#99CC00", "#FFBB33", "#FF4444"]//modelData 颜色数据
// ColorSquare{
// id:red;
// color: modelData;
// active: parent.paintColor == color//当选中一个colorSquare时,当前画笔颜色为选中的颜色
// onClicked: {
// parent.paintColor = color
// }
// }
// }
Button {
text: "Clear"
onClicked: {
canvas.clear()
}
}
Button{
text: "line";
onClicked: {
paintType = "line";
//canvas.requestPaint();
}
}
Button{
text: "rect"
onClicked: {
paintType = "rect";
// canvas.requestPaint();
}
}
Button{
text: "circle"
onClicked: {
paintType = "circle";
// canvas.requestPaint();
}
}
Button{
text: "curve"
onClicked: {
paintType = "curve";
// canvas.requestPaint();
}
}
}
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
}
//鼠标点击坐标位置
function clear() {//此清除有问题
var ctx = getContext("2d");
ctx.reset();
canvas.requestPaint();
}
onPaint: {
var ctx = getContext("2d")
ctx.lineWidtn = 10
ctx.strokeStyle = canvas.color;
// ctx.fillStyle = canvas.color;//若想要填充的 此不注释
if(isMouseMoveEnable)
ctx.clearRect(0,0,width,height) //这句话要换成一个只清理临时的对象
ctx.beginPath()
if(paintType === "line")
{
ctx.moveTo(startX,startY)
startX = area.mouseX;
startY = area.mouseY;
ctx.lineTo(stopX,stopY)
stopX = area.mouseX;
stopY = area.mouseY;
}
if(paintType === "rect")
{
//ctx.fillRect(startX,startY,stopX-startX,stopY-startY)//填充类型
//ctx.clearRect(0,0,width,height)
ctx.strokeRect(startX,startY,stopX-startX,stopY-startY)//非填充
}
if(paintType === "circle")
{
ctx.arc(startX,startY,Math.sqrt(Math.pow((stopX-startX),2)+Math.pow((stopY-startY),2)),0,Math.PI*2)
}
if(paintType === "curve"){
//未实现
ctx.arcTo(startX,startY,stopX,stopY,Math.sqrt(Math.pow((stopX-startX),2)+Math.pow((stopY-startY),2)))
}
//ctx.fill();
ctx.stroke()
}
MouseArea{
id:area;
anchors.fill:
parent;
onPressed: {
//第一次点击鼠标记录起始点
startX = mouse.x;
startY = mouse.y;
isMouseMoveEnable=true
}
onReleased: {
stopX = mouse.x;
stopY = mouse.y;
isMouseMoveEnable=false
}
onPositionChanged: {
//鼠标移动动态记录结束点,并且绘制
if(isMouseMoveEnable) {
// console.log("mouse posiont changed....")
stopX = mouse.x;
stopY = mouse.y;
canvas.requestPaint();
}
}
}
}