作者: 狐狸家的魚
Github: 八至
版權聲明:如需轉載請獲取授權和聯系作者
用純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();
}
}
}
}
同樣的,也可以改成鼠標點擊繪制時有預覽路徑,結合上面的方法可以修改
作者:狐狸家的魚
本文鏈接:https://www.cnblogs.com/suRimn/p/9849195.html
聲明:如需轉載請聯系作者或者附上原文鏈接