【Qt】二维绘图

 

原理

  • QPainter用来执行绘图操作
  • QPaintDevice提供绘图设备,它是一个二维空间的抽象,可以使用QPainter在其上进行绘制
  • QPaintEngine介于QPainterQPaintDevice对象之间,它的存在使得QPainter可以以统一的方法在不同QPaintDevice上绘图

 

QPainter类

常用函数

1.设置绘图工具

  • setPen          //设置画笔
  • setBrush       //设置画刷
  • setFont         //设置字体
  • setBackgroundMode     //设置背景模式

2.绘制图形和文字

  • drawPoint()        //点
  • drawPoints()      //多个点
  • drawLine()         //线
  • drawLines()       //多条线
  • drawRect()        //矩形
  • drawRects()       //多个矩形
  • drawRoundedRect()     //圆角矩形
  • drawEllipse()       //椭圆
  • drawArc()            //圆弧
  • drawPie()            //扇形图
  • drawPolyline()     //多折线
  • drawPolygon()     //多边形
  • drawConvexPolygon()     //凸多边形
  • drawPixmap()/ drawImage()       //位图
  • drawText()            //文字
  • drawPath()            //按路径绘制

painter->drawLine(20, 20, 100, 120);              //画一条 (20,20) 到 (100,120) 的线段

painter->drawEllipse(20,20,210,160);              //椭圆左上角的坐标+椭圆的宽度和高度

painter->drawRect(20,20,210,160);                  //矩形左上角坐标+宽和高

painter->drawRoundRect(20,20,210,160,50,50);          //最后两个参数决定圆角大小,可为0到99的数值(99代表圆)

paint->drawPie(20,20,210,160,0,500);              //前四个参数定义与drawEllipse()相同。后两个参数定义圆的样式。0为起始角度(单                                                                               位为1/16度),500为扇形所展开的角度(单位也为1/16)

paint->drawArc(20,20,210,160,500,1000);        //drawArc()函数与drawPie()函数的参数完全相同

3.坐标变换

  • rotate()         //旋转
  • translate()     //平移
  • scale()           //缩放
  • shear()          //扭曲

绘图一般流程

  1. 定义QPainter对象(变量)

  2. paintEvent函数中,使用对象的方法(成员函数)绘制各种图形或文字

  3. 也可以在其他事件处理函数中用以上方法绘图,并且调用repaint函数重新刷新屏幕(重绘)

举例

1.Widget.h

protected:
void paintEvent(QPaintEvent *);        //函数名和参数不能错,不是自定义函数

2.Widget.cpp

void Widget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setPen(Qt::blue);	   //设置蓝色画笔
    painter.setFont(QFont("Arial", 30));	//设置字体
    //在客户区中央输出文字
    painter.drawText(rect(), Qt::AlignCenter, "Qt");
    painter.drawEllipse(QRect(0, 0, width()-1, height()-1));	
}

运行结果: 

 

QPen类

QT Road之【QPen】

 

点类(QPoint 和 QPointF) 

 QPointQPointF 类代表一个坐标点。它包含一个横坐标和一个纵坐标,前者数值为int型,后者数值为float型。

  • void setX(int x);       //设置横坐标为 x
  • void setY(int y);        //设置纵坐标为 y

 举例

1.画直线

    QPoint  p1(0,0), p2(100,100);
    painter.drawLine(p1,p2);

2.画多边形

    QPoint  points[4] = { 
       QPoint(10,80),QPoint(20,10), 
       QPoint(80,30),QPoint(90,70)
        };
    painter.drawPolygon(points, 4);

 

线段类(QLine 和 QLineF)

Qline QLineF代表一个线段,前者数值为int型,后者数值为float型。

构造函数

  • QLine::QLine(const QPoint & p1,const QPoint & p2)       //线段(x1,y1)(x2,y2)

QLine::QLine(int x1, int y1, int x2, int y2)

其他函数 

  • void QLine::setP1(const QPoint & p1)          //设置点1
  • void QLine::setP2(const QPoint & p2)          //设置点2
  • void QLine::setLine(int x1, int y1, int x2, int y2         //设置点(x1,y1)和(x2,y2)
  • int x1() / x2() / y1() / y2()                               //返回坐标x1,x2,y1,y2

 

矩形类(QRect 和 QRectF)

 构造函数

  • QRect  r1(100, 200, 110, 160);             //矩形对象 r1的左上角为(100,200),宽110、高160

其他函数

  • int x();                                  //获取左上角x
  • int y();                                  //获取左上角y坐标
  • void setX(int x);                   //设置左上角x坐标
  • void setY(int y);                   //设置左上角y坐标
  • int width();                           //获取矩形宽度
  • int height();                          //获取矩形高度
  • void setWidth(int width);      //设置矩形宽度
  • void setHeight(int height);    //设置矩形高度
  • void moveTo(int x, int y)       //将矩形左上角移动到(x,y)
  • void moveTo(const QPoint & pos)              //将矩形左上角移动到坐标点pos
  • QPoint center ()                    //返回矩形中心点
  • bool contains ( int x, int y )    //判断点是否在当前矩形内部
  • bool contains(const QPoint &point, bool proper=false)

 

颜色类(QColor)

QColor支持RGBHSVCMYK颜色模型。还支持alpha混合(透明度)的模式。RGB是面向硬件的模型,颜色由红绿蓝三种基色混合而成。

  • QColor( 250, 250, 200)     //定义颜色对象,红绿蓝分别是250250200
  • QColor(255, 0, 0, 127)      // 第四个为透明度(其中透明度为0~2550完全透明、255为不透明)
  • QColor(Qt::green)             //使用Qt的枚举类型

 

屏幕重绘

Qt中,paintEvent函数是进行重绘的。只要出现以下几种情况,系统就会产生屏幕重绘事件,从而自动调用paintEvent方法。

  1. 当窗口部件第一次显示时
  2. 重新调整窗口部件大小,或者窗口从隐藏到显示;
  3. 当窗口部件被其他部件遮挡,然后又再次显示出来时,就会对隐藏的区域产生一个重绘事件

但是如果遇到如下情况:

  • 有些时候,程序窗口并没有发生大小改变或从隐藏到显示等情况(即没有产生屏幕重绘事件),但是由于某种情况的发生也需要对窗口进行重绘。

  • 比如要实现用户点击窗口内任意位置就在此处画一个圆,或者随着时间流逝周期性的在窗口中显示时间,这时就需要主动地进行屏幕重绘。

此时就需要QWidget的函数update()或者repaint()可以实现主动屏幕重绘(就是调用一次paintEvent函数?应该是。。)

update()和 repaint()差别:

  • repaint()函数被调用之后,立即执行重绘。因此repaint最快的
  • update()调用后并不立即重绘,而是将重绘事件放入事件循环中,由主窗口的事件循环来统一调度

update()函数

  • void QWidget::update(int x, int y, int w, int h)             //重绘(x, y)为左上角,w为宽,h为高的区域(重绘一个矩形区域
  • void QWidget::update(const QRect & rect)

除此之外,还有timerEvent函数,它在timer每次到时间时都会被触发一次

 

简单实例(文字,线段,矩形,椭圆,图片的绘制)

Qt 之图形(QPainter 的基本绘图)

 

综合实例——时钟的绘制

新建基于QWidget类的程序。创建时取消ui界面

1.Widget.h

    float radius;       // 时钟半径
    //指针针尖坐标
    int xSecond, ySecond, xMinute, yMinute, xHour, yHour;    
    int xCenter, yCenter;	//时钟中心坐标
    int second,minute,hour;	//时分秒的实际数字
    void CalcPosition();	//计算三种指针针尖坐标的函数
protected:
    void paintEvent(QPaintEvent *);			
    void timerEvent(QTimerEvent *event);	

2.Widget.cpp

#include <qmath.h>         // 数学库
#include <QPainter>
#define PI 3.14159265       // 圆周率

void Widget::CalcPosition() 
{   float secondHandLen, minuteHandLen, hourHandLen;
    secondHandLen = radius*0.8;      //计算秒针长度
    minuteHandLen = radius*0.65;     //计算分针长度
    hourHandLen = radius*0.5;        //计算时针长度
    // 计算秒针针尖位置
    xSecond = xCenter+secondHandLen*cos(second*PI/30-PI/2);
    ySecond = yCenter+secondHandLen*sin(second*PI/30-PI/2);
    // 计算分针针尖位置
    xMinute = xCenter+minuteHandLen*cos(minute*PI/30-PI/2);
    yMinute = yCenter+minuteHandLen*sin(minute*PI/30-PI/2);
    // 计算时针针尖位置
    xHour=xCenter + hourHandLen*cos((hour+1.0*minute/60)*PI/6-PI/2);
    yHour = yCenter + hourHandLen*sin((hour+1.0*minute/60)*PI/6-PI/2);
}

Widget::Widget(QWidget *parent) : QWidget(parent)
{
    radius = 100;  
    xCenter = 120, yCenter=120;
    hour = 3, minute = 56, second = 55;       //初始时间 3:56:55
    CalcPosition();  //计算初始位置用于第一次显示
    startTimer(100); //启动定时器,为了便于观察,加速10倍
}

void Widget::timerEvent(QTimerEvent *e)
{
    CalcPosition();     // 计算位置
    second++;         // 秒增加
    if(second==60) 
    {
         second = 0;
         minute++;    // 分增加
    }
    if(minute==60) {
         minute = 0;
         hour++;      // 时增加
    }
    update();
}

void Widget::paintEvent(QPaintEvent *) {
    QPainter painter(this);
    QPen pen;    // 画笔的使用请参考下一节
    painter.drawEllipse(QPointF(120.0,120.0),radius,radius);  
    painter.drawLine(xCenter,yCenter, xSecond,ySecond);  //秒针
    pen.setWidth(2);     // 画笔设置宽度 
    painter.setPen(pen);   //使用画笔
    painter.drawLine(xCenter,yCenter, xMinute,yMinute);   //分针
    pen.setWidth(4);
    painter.setPen(pen);
    painter.drawLine(xCenter,yCenter, xHour,yHour);    // 时针
}

CalcPosition() 函数中计算针尖角度其实可以不用这么绕来绕去,ppt中给出的解释是:

注意,Qt中坐标是x轴横向向右为正,y轴垂直向下为正,所以0度对应水平向右,顺时针方向是度数增加。但是钟表应该是竖直向上位置为0度,顺时针方向为度数增加。所以这里计算旋转度数时减去PI/2弧度(即90度)。

可以画个sin和cos的波浪图,然后看指针转一圈对于x和y轴是要加还是要减,与波浪图相对应即可,不行的话+/- π/2 即可(左加右减)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值