上一篇:QPainter实现简单的绘图程序(绘图工具)
前言
gitee工程地址: PaintTool_03
学习了简单的绘图工具后,程序略显基础与简单。接下来就开始改善上一篇文章的程序,增添撤回和橡皮擦功能。
为了偷懒,我直接上传工程,然后解释一些程序的关键点,因为程序稍大了后即使一步一步分析思路,还不如自己找关键程序段分析来的快。
撤回功能的理解
上篇的程序可以看到,画基本图形与画笔都可以用path来存储,那么我们只需要引入QStack<QPainterPath>
栈来存储每一次的绘图,这样便可以通过出栈的方式来撤销一步绘图
//变量声明
QPainterPath path; //临时绘画路径
QStack<QPainterPath> paths; //绘画路径栈
拆分的理解
- 普通图的撤销(圆形、矩形、直线)。
- 画笔工具的撤销。
- 橡皮擦工具。
一、重绘函数的写法
/*
*image相当于所有绘图的储存容器,而path是当前正在绘制的图形
*可以理解为:对于基本图形,是在松开鼠标后才将最终的path存到image中
*对于画笔和擦皮来说,是直接画在image里,因为鼠标路径就是最终绘图路径,不需要path来缓存(希望这里能仔细理解)
*/
if(event->type()==QEvent::Paint){
painter.begin(this);
painter.drawImage(0,0,image); //绘制画好的图片
if(!path.isEmpty()){ //path代表当前正在画的路径,不为空说明正在画图,那么先把这个路径绘制出来。
if(num==5)//如果是橡皮,则设置painter为擦除模式,将绘画处擦出成完全透明的区域
painter.setCompositionMode(QPainter::CompositionMode_Clear);
else //否则,即不是橡皮工具,则设置基础的画笔样式
Widget::setPenStyle();
painter.drawPath(path);
}
painter.end();
}
二、绘制判断
if(event->type()==QEvent::MouseButtonPress){
first = last = e->pos();
if(num==4){
path = QPainterPath(first);
paths.push(path);
}
this->update();
}
......
......
//下面判断存在于鼠标移动事件中
//1矩形 2圆形 3直线 4画笔 5橡皮
switch (num) {
case 1:
path.clear();//每次移动都重新绘制路径
//normalized()方法可以重新整理矩形,让矩形的左上与右下两个点处于正确的相对位置
path.addRect(QRect(first,last).normalized());
break;
case 2:
path.clear();
path.addEllipse(QRect(first,last).normalized());
break;
case 3:
path.clear();
path = QPainterPath(first); //设置绘画路径的落笔点,默认为0,0
path.lineTo(last); //当前笔所在点画到last点处,那么现在笔就会在last点的位置,这也是为什么上面要将落笔点设置为first
break;
case 4: //画笔工具
path.lineTo(last);
pointsNum++; //计数当前点的个数
if(pointsNum>255){ //超过255
Widget::drawPathtoImage(); //那么视作path存满了,直接画在image里(存多了会出现第一篇的情况,花圈出现卡顿呈多边形的现象)
paths.last().addPath(path); //这里看鼠标按下事件里面的特判,如果是画笔工具,那么提前添加了一个空路径,
//只要这次绘画没断笔,是一条线,则加入到属于当前路径的变量中,这样撤回时便不是只撤回255个点的路径,而是一整条线
path.clear(); //清空临时绘图路径
path = QPainterPath(last); //并将笔落在最后一次落笔的位置,这样才可以将线连起来
pointsNum=1; //重新设置path路径中点的个数
}
break;
case 5: //橡皮擦
painter.setCompositionMode(QPainter::CompositionMode_Clear);//设置成清除模式
painter.setBrush(QColor(0,0,0,0)); //设置成画刷填充
painter.drawEllipse(last,10,10); //直接擦除image中以落笔处为中心,半径为10的圆
break;
}
......
......
三、橡皮擦
......
......
switch (num) {
......
......
case 5: //橡皮擦
painter.setCompositionMode(QPainter::CompositionMode_Clear);//设置成清除模式
painter.setBrush(QColor(0,0,0,0)); //设置成画刷填充
painter.drawEllipse(last,10,10); //直接擦除image中以落笔处为中心,半径为10的圆
break;
}
......
......
该程序仍是初学者的练习程序,改进需要自己动脑,这里只是一个思路,想要直接找成品完成项的同志,就不要在这里浪费时间了,本篇文章只是练习为目的,也提供了一个实现功能的思路,而,已。
感谢各位的观看
下一篇: QPainterPath路径类的使用(图像移动)
tips: 今日蓝桥杯成绩出炉,在下作为软件工程的人,居然拿了电子类嵌入式的省一,实属荣幸。
即使我心中的只有那充满铜臭味的金钱奖励