作者: 狐狸家的鱼

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学习笔记(二)-纯qml画图实现canvas画板-鼠标画图的更多相关文章

  1. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78516 ...

  2. QML学习笔记(六)- 简单计时器和定时器

    做一个简单的qml计时器和定时器,左键触发计时,右键触发定时 GitHub:八至 作者:狐狸家的鱼 本文链接:QML学习笔记(六)- 简单计时器和定时器 左键点击按钮,触发计时器,中键可以暂停计时,同 ...

  3. QML学习笔记(五)— 做一个简单的待做事项列表

    做一个简单的QML待做事项列表,能够动态添加和删除和编辑数据 GitHub:八至 作者:狐狸家的鱼 本文链接:QML学习笔记(五)— 做一个待做事项列表 主要用到QML:ListView 效果 全部代 ...

  4. 纯JS实现KeyboardNav(学习笔记)二

    纯JS实现KeyboardNav(学习笔记)二 这篇博客只是自己的学习笔记,供日后复习所用,没有经过精心排版,也没有按逻辑编写 这篇主要是添加css,优化js编写逻辑和代码排版 GitHub项目源码 ...

  5. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  6. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  7. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  8. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  9. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

随机推荐

  1. [转帖]Windows平台卸载Oracle的办法

    1.首先打开服务:选中此电脑->点击右键->选择管理->选择服务和应用程序->服务 在右边查看并停止以 oracle开头的服务(选中正在运行的以oracle开头的服务-> ...

  2. Laravel 5.2+ 使用url()全局函数返回前一个页面的地址

    注意:文章标题中5.2+表示该文章内容可向上兼容,适用于Laravel版本5.2及更高(目前最新为5.6),但不可向下兼容,即不适用于5.2版本以下.推荐大家花一点点时间,将自己的Laravel更新至 ...

  3. MyBatis源码分析1 参数映射分析

    首先我们拿出之前的代码,在如图位置打上断点,开始调试 我们规定了一个mapper接口,而调用了mapper接口的getEmpByIdAndLastName,我们并没有实现这个接口,这是因为Mybati ...

  4. 离线安装redis-cluster

    #离线安装redis-cluster https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.5.tar.gz #安装ruby .tar.gz cd rub ...

  5. WinForm中在非UI线程更改控件值的办法

    从非UI线程调用UI控件赋值.或进行其他更新UI的操作的话,会出现异常: System.InvalidOperationException:“线程间操作无效: 从不是创建控件“xxx”的线程访问它.” ...

  6. 【python练习题】程序10

    #10.题目:暂停一秒输出,并格式化当前时间. import time print(time.time())#timestamp print(time.localtime(time.time()))# ...

  7. Linux下的好用的编辑软件Remarkable

    Linux下的好用的编辑软件Remarkable最近着手开始学习Linux,就想着找一款好用的编辑器作笔记,在网上爬了些贴选择了Remarkable.官网崩了,有没有梯子,废了好大力气才装好.于是把资 ...

  8. Spring Boot自动配置与Spring 条件化配置

    SpringBoot自动配置 SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,简化开发时间,无需浪费时间讨论具体的Spring配置,只需考虑如何利用SpringBoot的自动配置即 ...

  9. linux中安装gcc

    在使用CentOS的yum -y install  时 可以先进入  /etc/yum.repos.d/ 文件下,将CentOS-Base.repo文件名改为CentOS-Base.repo.bak使 ...

  10. 洛谷P2055假期的宿舍

    题目 此题主要是考察二分图匹配,而二分图匹配最主要的就是建图,而图一般都是要分成两个部分来分,比如该题就需要先将在学校住的人和床连在一起,因为在学校住就会与一个床.然后每两个人之间假如他们相互认识就可 ...