使用QPainter、QPainterPath、QRegion绘图实践

摘自:https://blog.csdn.net/wanghualin033/article/details/78633604

使用qt的QPainter可以绘制出任何你想要的图形,同时也须要一定的功底;

这里是个人使用的一些实践例子,以作学习和备忘。本次介绍主要有画弦、
矩形、圆、椭圆、QPainterPath一次性画多个、画贝塞尔曲线、画扇形、
画弧、裁剪、掩码等。
一、画弦

    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {
        setAutoFillBackground(true);
        QPalette pal = palette();
        pal.setBrush(QPalette::Background,Qt::black);
        setPalette(pal); //设置背景色
        
        resize(600,480); //调整大小
        new QPushButton("hello",this); //重写paintEvent不会影响该对象的子控件
    }
    void Widget::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
        //设置反锯齿
        painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::Qt4CompatiblePainting);
        painter.setPen(Qt::yellow); //设置画笔颜色
       //画弦,该弦在QRect(10.0, 30.0, 80.0, 60.0)的内切椭圆上,并且起始角度为30(3点钟为0度,逆时针为正),跨度为120
        painter.drawChord(10.0, 30.0, 80.0, 60.0,30 * 16, 120 * 16);
    }


可以看到重写paintEvent并为会影响该控件的其它子控件。
二、画椭圆和圆

painter.drawEllipse(QPoint(width()/2,height()/2),width()/2 - 10,height()/2 - 10) //有多种画法,这里是指定圆心和x、y轴的半径;当x、y相等时就是画圆了


三、画矩形

    painter.drawRect(width()/2,height()/2,100,100); //以矩形左上角为顶点开画

四、画扇形

painter.drawPie(width()/2 - 50,height()/2 - 50,100,100,30 * 16,120 * 16); //在矩形内切椭圆上画,3点钟为0度,逆时针为正,角度要乘以16(参考文档)

五、QPainter的save()与restore()方法

        QPainter painter(this);
        //设置反锯齿
        painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::Qt4CompatiblePainting);
        painter.setPen(Qt::yellow); //设置画笔颜色
        painter.drawPie(width()/2 - 50,height()/2 - 50,100,100,30 * 16,120 * 16); //在矩形内切椭圆上画,3点钟为0度,逆时针为正,角度要乘以16(参考文档)
        painter.save(); //保存painter当前状态,后续紧跟一个restore()方法还原到这个状态
        painter.setPen(Qt::white);
        painter.drawRect(50,50,80,100); //画一个白色的矩形
        painter.restore(); //还原到前一个保存状态
        painter.drawRect(150,150,50,50); //用前一个保存的painter状态,画一个矩形

六、坐标平移

        painter.setPen(Qt::yellow); //设置画笔颜色
        painter.translate(width()/2,height()/2); //将坐标第原点移动到中心
        painter.drawRect(0,0,100,100);


另外QPainter还有setTransform()方法用于指定某个轴旋转,这个旋转可以让图形从屏幕里面到外边旋转,配合闹钟可以做出动画。
七、resetMatrix()方法,还原到默认坐标系

        painter.setPen(Qt::yellow); //设置画笔颜色
        painter.translate(width()/2 - 50 ,height()/2 - 50);
        painter.resetMatrix();
        painter.drawEllipse(0,0,100,100);


八、画边角带弧度的矩形

        painter.setPen(Qt::yellow); //设置画笔颜色
        painter.drawRoundRect(QRect(50,50,100,100),50,50);


九、掩码设置

        QRegion maskRegion(-7,-30,width() + 14,height() + 67);
        setMask(maskRegion.subtracted(QRegion(width()/2 - 70,height()/2 - 30,140,60,QRegion::Ellipse)));


设置为掩码的QRegion将可见,其于的不可见。这里要熟悉QRegion的一些用法

QRegion::intersected(constQRegion &r) const 两个区域相交的部分
QRegion::subtracted(constQRegion &r) const 不包含r的区域
QRegion::xored(constQRegion &r) const 两个区域的并集去掉交集剩下的部分
另外支持运算符重载意义和这个一样的。
十、裁剪

        painter.setPen(Qt::yellow); //设置画笔颜色
        painter.setClipRegion(QRegion(width()/2 - 100,height()/2 - 100,200,200)); //设置一个裁剪区域
        painter.setPen(Qt::white);
        painter.drawRect(painter.clipRegion().boundingRect());
        painter.setPen(Qt::yellow);
        painter.setBrush(QBrush(Qt::red));
        painter.drawEllipse(width()/2 - 80,height()/2 - 80,200,200); //超出裁剪区域的不画


setClipRegion()方法会自动设置setClipping()为true。当此次绘画结束后;如果后续绘画的区域没有在裁剪区域内,则不会显示;这时需要在裁剪绘画结束
后调用setClipping()传入false,使裁剪失效,这样就可以正常显示了
十一、画圆环

        painter.setPen(Qt::yellow); //设置画笔颜色
        QRegion r1(width()/2 - 50,height()/2 - 50,100,100,QRegion::Ellipse);
        QRegion r2(width()/2 - 100,height()/2 - 100,200,200,QRegion::Ellipse);
        painter.setClipRegion(r2 - r1);
        painter.fillRect(r2.boundingRect(),QBrush(Qt::red));

这里我想到的有两种方法;一、是画一个红色的大圆,再到中间画一个黑色(或透明)的小圆。
二、是构造一个圆环的QRegion使用QPainter的setClipRegion()方法使得只有在圆环区域内图形才能显示。
这里我使用的是第二种方法。
十二、用QPainterPath一次画多个图案

        painter.setPen(Qt::yellow); //设置画笔颜色
        QPainterPath path;
        path.addText(10,10,painter.font(),"Qt");
        path.moveTo(10,50);
        path.lineTo(120,50);
        path.addRoundedRect(10,80,80,80,5,5);
        painter.drawPath(path);

QPainterPath默认的起点在(0,0),在lineTo()之后,会将path的自动起点位置移到lineTo的点。addRect()或者addRoundedRect()之后会自动将起点移到Rect的左上角顶点
十三、使用QPainterPath的arcMoveTo和arcTo画弧或扇形

        painter.setPen(Qt::yellow); //设置画笔颜色
        QPainterPath path;
        path.arcMoveTo(width()/2 - 100,height()/2 - 100, 200,200,30); //将path的起点移到一个椭圆(以3点钟为0度,逆时针为正)距离角度0点为30度的椭圆上,该椭圆是rect(100,280,120,120)的内切椭圆
        path.arcTo(width()/2 - 100,height()/2 - 100, 200,200,30,120);
        painter.drawPath(path);


arcMoveTo其实就是为了设置arcTo绘画的起点,两个函数都是以一个矩形的内切椭圆的形式传参。如果是扇形的话

        painter.setPen(Qt::yellow); //设置画笔颜色
        QPainterPath path;
        path.moveTo(width()/2,height()/2);
        path.arcTo(width()/2 - 100,height()/2 - 100, 200,200,30,120);
        painter.drawPath(path);


我们只需要设置起画起点在椭圆中心就可以了,因为arcTo是先从QPainterPath起点到以传入参数应该起画的点之间连接再开画。
这里并不是一个完整的扇形,因为arcTo是画弧的;画完不会连接此次绘画的起点,这里需要我们手动连接,最简单的方法是调用
QPainterPath的closeSubpath()直接将Path绘画终点与起点闭合。

       painter.setPen(Qt::yellow); //设置画笔颜色
        QPainterPath path;
        path.moveTo(width()/2,height()/2);
        path.arcTo(width()/2 - 100,height()/2 - 100, 200,200,30,120);
        path.closeSubpath();
        painter.drawPath(path);

十四、使用QPainterPath画贝塞尔曲线

        painter.setPen(Qt::yellow); //设置画笔颜色
        QPainterPath cubPath;
        cubPath.cubicTo(170,50,90,200,width(),height());//传入点1(170,50),点2(90,200),endPoint(width(),heigt())
        cubPath.addEllipse(170 - 3,50 - 3,6,6); //以点1为圆心画圆
        cubPath.addText(180,60,painter.font(),QStringLiteral("Point1")); //标记点1
        cubPath.addEllipse(90 - 3,200 - 3,6,6);//以点2为圆心画圆
        cubPath.addText(100,210,painter.font(),QStringLiteral("Point2"));//标记点2
        painter.drawPath(cubPath);

如果加个画刷颜色就可以变成这样

    painter.setPen(Qt::yellow); //设置画笔颜色
        QPainterPath cubPath;
        cubPath.cubicTo(170,50,90,200,width(),height());//传入点1(170,50),点2(90,200),endPoint(width(),heigt())
        cubPath.addEllipse(170 - 3,50 - 3,6,6); //以点1为圆心画圆
        cubPath.addText(180,60,painter.font(),QStringLiteral("Point1")); //标记点1
        cubPath.addEllipse(90 - 3,200 - 3,6,6);//以点2为圆心画圆
        cubPath.addText(100,210,painter.font(),QStringLiteral("Point2"));//标记点2
        painter.setBrush(QBrush(Qt::lightGray));
        painter.drawPath(cubPath);

---------------------
作者:程序开发人生
来源:CSDN
原文:https://blog.csdn.net/wanghualin033/article/details/78633604?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值