QT踩坑第九天(2D绘图)

1、2D绘图简介

1.1 为什么需要2D绘图
在Qt界面编程中,通常会遇到使用Qt自带控件不能解决的问题,这时2D绘图给我们提 供了专用定制化的工具。
1.2 QPainter介绍
2D绘图离不开QPainter,可以把QPainter想象成一个画笔,开发人员拿着画笔理论上 是可以绘制任何你想要的图形。QPainter 一般在一个部件(widget)重绘事件( PaintEvent )的处理函数paintEvent ()中进行绘制,首先要创建QPainter 对象(画 笔),然后进行图形的绘制。
1.3 QPainter中常用的图形绘制函数

drawArc() 弧
drawChord() 弦
drawConvexPolygon() 凸多边形
drawEllipse() 椭圆,注意椭圆是先整个框,然后逼近…
drawImage() 图像
drawLine() 线
drawLines() 多条线
drawPath() 路径; 想到哪就去哪,但是必须是直的
drawPicture() 按QPainter指令绘制 区分drawImage、drawPixmap,大家可以试一把
drawPie() 扇形
drawPixmap() 图像 1.8给出了例子 image pixmap piture
drawPoint() 点
drawPoints() 多个点
drawPolygon() 多边形
drawPolyline() 多折线
drawRect() 矩形
drawRects() 多个矩形
drawRoundRect() 圆角矩形
drawText() 文字
drawTiledPixmap() 平铺图像
drawLineSegments() 绘制折线
1.4 画笔(QPen)与画刷(QBrush)
QPen
QPen定义了用于QPainter应该怎样画线或者轮廓线。画笔具有样式style() 、宽 度width() 、画刷brush() 、笔帽样式capStyle()和连接样式joinStyle()等属性。画 笔的样式style()定义了线的样式。画刷brush()用于填充画笔所绘制的线条。笔帽 样式capStyle()定义了使用QPainter绘制的线的末端;连接样式joinStyle()则定义 了两条线如何连接起来。画笔宽度width()或widthF()定义了画笔的宽。注意,不 存在宽度为 0 的线。假设你设置 width 为 0,QPainter依然会绘制出一条线,而 这个线的宽度为 1 像素。也就是说,画笔宽度通常至少是 1 像素。
QBrush
QBrush 类提供了画刷来对图形进行填充, 一个画刷具有样式(style)、颜色 (color)、渐变( gradient )、文理(texture)四个可设置属性。 可能用到Brush的样式、颜色、填充方式 (后两者是重点) const QColor &QBrush::color() const 获取当前Brush颜色 void QBrush::setColor(const QColor &color) 设置当前Brush颜色 。
渐变( gradient )定义了渐变填充。当创建Qbrush时,可以在构造函数中传入一个渐变 画笔对象用于构建画刷的渐变样式
1.5 探讨paintEvent什么时候调用

什么时候 paintEvent事件会产生
1 窗口隐藏­>显示 show
2 窗口缩小或者放大 resize
3 调用update()
4 调用repaint()
1.6 再谈坐标系及窗口移动原理
1.6.1 三个坐标的关系
在这里插入图片描述
windowDeskTopLeft 是指窗口到显示器左上角的坐标;

windowDeskTopLeft = this‐>geometry().topLeft()

注意:这里的this就是Widget对象,所以不包括应用程序的标题栏
在这里插入图片描述
mouseDeskTopLeft 是指鼠标(光标)到显示器左上角的坐标;

mouseDeskTopLeft  = event‐>globalPos();

mouseWindowTopLeft 是指鼠标(光标)到窗口左上角的坐标;

mouseWindowTopLeft = event‐>pos();

它们三者的关系是(矢量相减):

windowDeskTopLeft = mouseDeskTopLeft ­  mouseWindowTopLeft;

1.6.2 窗口移动的坐标关系
step1 记录鼠标左键按下时的mouseWindowTopLeft (响应mousePressEvent事件)
在这里插入图片描述
step2
鼠标移动时实时记录mouseWindowTopLeft (实时响应mouseMoveEvent事件, 需要setMouseTracking(true))
在这里插入图片描述
通过公式 windowDeskTopLeft = mouseDeskTopLeft ­ mouseWindowTopLeft; 计 算而来。
PS:在 中需要使用if (event­>buttons() & Qt::LeftButton)对左键进行过滤,不然鼠
标移动到哪里,不用按下左键窗口都会跟着走。
1.7 QPainter中scale
在这里插入图片描述scale:同比例缩放
The most commonly used transformations are scaling, rotation, translation and shearing. Use the scale() function to scale the coordinate system by a given offset, the rotate() function to rotate it clockwise and translate() to translate it (i.e. adding a given offset to the points). You can also twist the coordinate system around the origin using the shear() function. See the Affine Transformations example for a visualization of a sheared coordinate system.
scale参数
scale(qreal sx, qreal sy) sx = x方向scale的倍数 sy = y方向scale的倍数
1.8 QPainter中的save 和 restore
在2D绘制中经常遇到画笔坐标轴移动 画笔换色等等操作,在切换另一种操作前,需要
先save一次,完成后再restore一次。

2、QPainter 2D绘制基础实例

2.1 绘制文字
Q_UNUSED(event);//没有实质性的作用用来避免编译器警告

    void Widget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);//没有实质性的作用用来避免编译器警告
QPainter painter;
QFont  Font;
painter.begin(this);
painter.setPen(QColor(255,10,10));
Font.setPointSize(66);//设置字体大小
Font.setItalic(true);//斜体
painter.setFont(Font);//使字体生效
painter.drawText(rect(),Qt::AlignCenter,"Hello TZ EDU!");
painter.end();
    }

在这里插入图片描述
2.2 绘制直线

Q_UNUSED(this);
QPainter painter;
painter.begin(this);
painter.setPen(QPen(QColor(255,10,10),9));//这里设置画笔的颜色和线宽
painter.setRenderHint(QPainter::Antialiasing,true);//设置反锯齿
painter.drawLine(QPointF(0,this->height()),QPointF(this->width()/2,this->height()/2));//画直线,QPointF装起点,终点坐标
painter.end();

在这里插入图片描述
2.3 绘制矩形

 Q_UNUSED(this);
    QPainter painter;
    //设置反锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setPen(QPen(QColor(0,160,230),9));
    //设置画刷颜色
    painter.setBrush(QColor(255,160,90));
    //画矩形
    painter.drawRect(50,50,100,100);
    painter.end();

在这里插入图片描述
2.4 绘制弧形

 Q_UNUSED(event);
    QRectF rect(90.0,90.0,80.0,90.0);
    int startAngle=30*16;
    //跨越度数
    int spanAngle=120*16;
    QPainter painter;
    painter.begin(this);
    //设置反锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setPen(QPen(QColor(0,160,230),2));
    //painter.drawRect(rect);画矩形
    //画弧
    //drawArc需要三个参数:起始角度、跨度、位置矩阵;
    painter.drawArc(rect,startAngle,spanAngle);
    painter.end();

这里需要了解弧度的基本知识
在这里插入图片描述
drawArc需要三个参数:起始角度、跨度、位置矩阵;注意角度被分成了十六分之 一,就是说,如果要 30 度,就需是 30*16。
2.5 绘制椭圆

  //椭圆也是在矩形里面
    Q_UNUSED(this);
    QPainter painter;
    painter.begin(this);
    //设置反锯齿
    painter.setRenderHint(QPainter::Antialiasing,true);
    painter.setPen(QPen(QColor(0,160,230),2));
    QRectF rectangle2(10.0,20.0,80.0,60.0);
    painter.drawRect(rectangle2);
    painter.drawEllipse(rectangle2);
    painter.end();

在这里插入图片描述
2.6 绘制多边形

   Q_UNUSED(this);
    //这里用 QPainter painter(this); 代替了上面的begin 和 end
    QPainter painter(this);
    static const QPoint points[4]={QPoint(10.0,80.0),
                                   QPoint(20.0,10.0),
                                   QPoint(80.0,30.0),
                                   QPoint(90.0,70.0)};
    painter.drawConvexPolygon(points,4);

在这里插入图片描述
2.7 绘制路径

   //经典的贝塞尔曲线
    QPainter painter(this);
    QPainterPath path;
    path.addRect(20,20,60,60);//添加矩形
    path.moveTo(0,0);//设置起始点
    path.cubicTo(99,0,50,50,99,99);//绘制上贝塞尔曲线
    path.cubicTo(0,99,50,50,0,0);//绘制下贝塞尔曲线
    path.setFillRule(Qt::OddEvenFill);//两种不同的填充模式,一个是全部填充,一个是去除重复
    painter.fillRect(0,0,100,100,Qt::white);//填充矩形
    painter.setPen(QPen(QColor(122,163,39)));//设置画笔
    painter.setBrush(QColor(122,163,39));//设置画刷颜色
    painter.drawPath(path);//绘制路径

在这里插入图片描述
2.8 三种方式绘图

 QPainter painter;
    //绘制image
    QImage image(100,100,QImage::Format_ARGB32);//大小100*100
    painter.begin(&image);
    painter.setPen(QPen((Qt::green),3));
    painter.setBrush(Qt::yellow);
    painter.drawRect(10,10,60,60);
    painter.drawText(10,10,60,60,Qt::AlignCenter,tr("QImage"));
    painter.setBrush(QColor(0,0,0,100));
    painter.drawRect(50,50,40,40);
    painter.end();
    //绘制pixmap
    QPixmap pix(100,100);//大小100*100
    painter.begin(&pix);
    painter.setPen(QPen(Qt::green,3));
    painter.setBrush(Qt::yellow);
    painter.drawRect(10,10,60,60);
    painter.drawText(10,10,60,60, Qt::AlignCenter,  tr("QBitmap"));
    painter.setBrush(QColor(0,0,0,100));
    painter.drawRect(50,50,40,40);
    painter.end();
    // 绘制bitmap
    QBitmap bit(100, 100);
            painter.begin(&bit);
            painter.setPen(QPen(Qt::green, 3));
            painter.setBrush(Qt::yellow);
            painter.drawRect(10, 10, 60, 60);
            painter.drawText(10, 10, 60, 60, Qt::AlignCenter,  tr("QBitmap"));
            painter.setBrush(QColor(0 , 0, 0, 100));
            painter.drawRect(50, 50, 40, 40);
            painter.end();
    //绘制picture
    QPicture picture;
    painter.begin(&picture);
    painter.setPen(QPen(Qt::green,3));
    painter.setBrush(Qt::yellow);
    painter.drawRect(10, 10, 60, 60);
    painter.drawText(10,10,60,60,Qt::AlignCenter,tr("QPicture"));
    painter.setBrush(QColor(0,0,0,100));
    painter.drawRect(50,50,40,40);
    painter.end();
    //在Widget部件上进行绘制
    painter.begin(this);
    painter.drawImage(50,20,image);
    painter.drawPixmap(200,20,pix);//左端起点(200,20)
    painter.drawPixmap(50,170,bit);
     painter.drawPicture(200, 170, picture);

在这里插入图片描述
这三种绘图方式都是QPaintDevice的子类
QImage
依赖软件,直接像素访问,适合大图片
既然依赖软件,那么就不需要用硬件GUI的线程了,可以开个软件的线程,可提高用户UI体验
QPixmap
(依赖硬件,加速显示,适合小图片)
QPixmap的设计本来就是用来加速显示,用paint绘图时用QPixmap会比其他类的效果好很多。
一般小图片用QPixmap。
QBitmap是QPixmap的一个子类,主要用于显示单色位图
当图片较大时,可以用QImage先把图片加载进来—调整大小—转成QPixmap输出
QPicture
保存绘图的状态(二进制文件)
2.9 反走样
抗锯齿( Anti­aliased)又称为反锯齿或者反走样,就是对图像的边缘进行平滑处
理,使其看起来更加柔和流畅的一种技术。QPainter 进行绘制时可以使用QPainter
::RenderHint 渲染提示来指定是否要使用抗锯齿功能,RenderHint 取值分为以下三
种。(这功能是在显卡中完成的)

常量描述
QPainter::Antialiasing边缘抗锯齿
QPainter::TextAntialiasing文字抗锯齿
QPainter::SmoothPixmapTransform平滑pixmap转换算法抗锯齿

心法:
a) 绘制文字用TextAntialiasing
b)有图片用SmoothPixmapTransform
c)其它用 Antialiasing
2.10 渐变与填充
在Qt中提供了三种渐变方式,分别是线性渐变,圆形渐变和圆锥渐变。(可以使用来设计出炫目的填充效果)
线性渐变
QPainter painter(this);
//从点(100,150)开始到点(300,150)结束,确定一条直线

  void Widget::paintEvent(QPaintEvent *event)
{
    QLinearGradient linerGradient(100,150,300,150);
    linerGradient.setColorAt(0,Qt::red);
    linerGradient.setColorAt(0.2,Qt::black);
    linerGradient.setColorAt(0.4,Qt::yellow);
    linerGradient.setColorAt(0.6,Qt::white);
    linerGradient.setColorAt(0.8,Qt::green);
    linerGradient.setColorAt(1.0,Qt::blue);
     //将直线开始点设为0,终点设为1,然后分段设置颜色
    painter.setBrush(linerGradient);
    painter.drawRect(100,100,200,200);
     //绘制矩形,线性渐变线正好在矩形的水平中心线上
     }

在这里插入图片描述
圆形渐变

   QPainter painter(this);
    //其中参数分别为圆形渐变的圆心(200,100),半径100,和焦点(200,100)
    //这里让焦点和圆心重合,从而形成从圆心向外渐变的效果
    QRadialGradient radialGradient(200,100,100,200,100);
    radialGradient.setColorAt(0,Qt::black);
    radialGradient.setColorAt(1,Qt::yellow);
    painter.setBrush(radialGradient);
    painter.drawEllipse(100,0,200,200);

在这里插入图片描述
锥形渐变

 QPainter painter(this);
    QConicalGradient conicalGradient(50,50,30);
    //圆心为(50,50),开始角度为0
    conicalGradient.setColorAt(0,Qt::green);
    conicalGradient.setColorAt(1,Qt::white);
     //从圆心的0度角开始逆时针填充
    painter.setBrush(conicalGradient);
    painter.drawEllipse(0,0,100,100);

在这里插入图片描述

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值