QPainter绘图工具的完善

本文档介绍了如何在QPainter基础上添加撤销和橡皮擦功能。通过使用QPainterPath和QStack来存储绘图路径,实现了撤销操作。同时详细解析了重绘函数、绘制判断及橡皮擦的实现细节,帮助读者理解如何在图形界面程序中实现这些高级功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇:QPainter实现简单的绘图程序(绘图工具)


前言

gitee工程地址: PaintTool_03

学习了简单的绘图工具后,程序略显基础与简单。接下来就开始改善上一篇文章的程序,增添撤回和橡皮擦功能。
为了偷懒,我直接上传工程,然后解释一些程序的关键点,因为程序稍大了后即使一步一步分析思路,还不如自己找关键程序段分析来的快。


在这里插入图片描述

撤回功能的理解

上篇的程序可以看到,画基本图形与画笔都可以用path来存储,那么我们只需要引入QStack<QPainterPath>栈来存储每一次的绘图,这样便可以通过出栈的方式来撤销一步绘图

//变量声明
QPainterPath path;          //临时绘画路径
QStack<QPainterPath> paths; //绘画路径栈

拆分的理解

  1. 普通图的撤销(圆形、矩形、直线)。
  2. 画笔工具的撤销。
  3. 橡皮擦工具。

一、重绘函数的写法

/*
*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: 今日蓝桥杯成绩出炉,在下作为软件工程的人,居然拿了电子类嵌入式的省一,实属荣幸。

即使我心中的只有那充满铜臭味的金钱奖励



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值