• qt 绘图


    QPainter绘图系统

    QPainter用来进行绘图操作的类。绘图设备一般包括Qwidget、Qpixmap、QImage.他们提供给QPainter画布。
    QPaintDevice是一个可以使用QPainter进行绘图的抽象二维界面。
    QPaintEngine给QPainter提供在不同设备上绘图的接口,QPaintEngine类由QPainter和QPaintDevice内部使用,应用程序一般无需使用QPaintEngine。
    绘图设备包括QWidget、QPixmap、QImage等。


    paintEvent世界和绘图区

    QWidget类及其子类是最常用的绘图设备,从QWidget类继承的类都有paintEvent()事件,只需要重定义此事件就行。  相当于windows mfc的onpaint函数。paintEvent里面的坐标默认是物理坐标(视口坐标)

    只要窗口部件需要被重绘就被调用。是repaint()或update()的结果。 几次调用update()的结果通常仅仅是一次paintEvent()调用。 Qt通常在paintEvent()调用之前擦除这个窗口部件的区域。

    update()相当于 mfc 的invalidate();迫使paintEvent虚函数被调用。

    QWidget绘图区就是其窗口内部区域。坐标系统的单位是像素。左上角坐标为(0,0)。这个坐标系统是物理坐标,称为视口(viewport)坐标

    高度:QWidget::height()

    宽度:QWidget::width()

    设置qwidget窗口大小的函数

    1.setMinimumSize(固定最小大小) setMaximumSize(固定最大大小)  能够设置初始大小

    2.setFixedSize   固定大小,  能够设置初始大小,但是之后就不能用鼠标调整窗口大小了

    3.resize   推荐使用的方法

    4.setGeometry 

    延伸到控件的缩放方式sizePolicy

    控件的 sizePolicy 说明控件在布局管理中的缩放方式。调用setsizepolicy函数实现。默认是按比例缩放的。

    Fixed:控件不能放大或者缩小,控件的大小就是它的sizeHint。
    Minimum:控件的sizeHint为控件的最小尺寸。控件不能小于这个sizeHint,但是可以
    放大。
    Maximum:控件的sizeHint为控件的最大尺寸,控件不能放大,但是可以缩小到它的最小的允许尺寸。
    Preferred:控件的sizeHint是它的sizeHint,但是可以放大或者缩小
    Expandint:控件可以自行增大或者缩小

    1. m_paddBtn = new QPushButton(tr("添加"));
    2. m_paddBtn->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed);

    延伸到控件的大小sizeHint

    这个属性所保存的 QSize 类型的值是一个被推荐给窗口或其它组件(为了方便下面统称为widget)的尺寸,也就是说一个 widget 该有多大,它的一个参考来源就是这个 sizeHint 属性的值,而这个值由 sizeHint() 函数来确定。

    1.在 widget 有 layout 的情况下,其 sizeHint() 函数返回的是有效值作为其自身实际尺寸的参考;
    2. sizeHint() 返回的值并不一定会作为 widget 的实际尺寸,因为 widget 的尺寸的决定还有其它因素作用;

    sizeHint为虚函数,重写该函数即可。virtual QSize sizeHint() const;

    QPainter绘图主要属性

    QPen:画笔,用于控制线条的颜色、宽度等。   

    setPen、setStyle(线条样式)、setCapStyle(线条端点样式)、setJoinStyle(线条连接样式)

    QBrush:画刷,用于填充颜色、渐变特性等。

      setBrush、setStyle(填充样式)

    渐变色:

    线性渐变:QLinearGradient

    辐射渐变:QRadialGradient

    圆锥形渐变:QConicalGradient

    1. //线性渐变
    2. QLinearGradient linearGrad(0,0,100,0);//从左到右,
    3. linearGrad.setColorAt(0,Qt::yellow);//起点颜色
    4. linearGrad.setColorAt(1,Qt::green);//终点颜色
    5. linearGrad.setSpread(QGradient::PadSpread); //展布模式
    6. painter.setBrush(linearGrad);

    QFont:字体属性,用于绘制文字时,设置文字的样式、大小等 

    setFont

    绘图

    点:drawPoint()、drawPoints()、

    线:drawLine()、

    区域:drawRect()

    文本:drawText()

    Qt提供了处理图像数据的类:QImage, QPixmap和QPicture。

    • QImage是为I/O和直接像素访问和操作而设计和优化的
    • QPixmap是为在屏幕上显示图像而设计和优化的。
    • QPicture类是一个记录和回放QPainter命令的绘制设备。

    drawPicture: QPicture 

    1.  QPicture picture;
    2.  QPainter painter;
    3.  painter.begin(&picture);           // paint in picture
    4.  painter.drawEllipse(10,20, 80,70); // draw an ellipse
    5.  painter.end();                     // painting done
    6.  picture.save("drawing.pic");       // save picture
    7. QPicture picture;
    8. QPainter painter;
    9. picture.load("drawing.pic");
    10. painter.begin(this);
    11. painter.drawPicture(0,0,picture);
    12. painter.end();

    drawPixmap:   QPixmap

    QPixmap绘图依赖硬件,QPixmap的设计本来就是用来加速显示,用paint绘图时用QPixmap会比其他类的效果好很多。一般小图片用QPixmap加载,和平台相关(在不同的平台可能绘制出的效果不一样)。QPixmap上绘图比较慢,但显示它则比较快(使用GPU处理,相对减轻了CPU的负担).

    可以直接使用构造函数,关联资源 ,如 QPixmap(":/res/python.jpg");也可以使用load、save进行加载或保存。

    load()加载图像文件作为QPixmap对象
    save()将QPixmap对象保存为文件

    QPximap在label中的使用:(其他按键控件也可使用)

    1. QLabel *label=new QLabel(this);
    2. label->resize(303,303);//设置大小
    3. QPixmap pixmap(":/image/456.png");
    4. pixmap.scaled(label->width(),label->height());
    5. label->setPixmap(pixmap);

    QPximap 在widget的paintevent函数绘制

    1. void Widget::paintEvent(QPaintEvent *event)
    2. {
    3. QPainter painter(this);
    4. QRect rect1(0,0,100,100);
    5. paint.drawPixmap(rect1,QPixmap(tr(":/res/about.png")));
    6. }

     QPximap ​​​​​​​对象保存

    1. QPixmap pixmap(width, height);
    2. QPainter painter(&pixmap);
    3. 调用painter的函数画图
    4. pixmap.save(PATH); //保存绘制好的图像

    drawImage   QImage

    QImage类提供了一个独立于硬件的图像表示,它允许直接访问像素数据,并且可以用作绘制设备;适合加载大图片;可以在线程中绘图,可以优化UI响应时间。绘制图片出来的效果和平台无关,QImage上绘图比较快,但显示它则比较慢。

    QImage的基本函数的使用与QPixmap类似,可以直接使用构造函数,关联资源

    1. QRect rect2(100,0,100,100);
    2. paint.drawImage(rect2,QImage(tr(":/res/about.png")));

    QPixmap与QImage的区别:

    QPixmap依赖于硬件,QImage不依赖于硬件。

    QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O、图片访问和像素修改而设计的。
    当图片小的情况下,直接用QPixmap进行加载,画图时无所谓,当图片大的时候如果直接用QPixmap进行加载,会占很大的内存,一般一张几十K的图片,用QPixmap加载进来会放大很多倍。

    所以一般图片大的情况下,用QImage进行加载,然后转乘QPixmap用户绘制。QPixmap绘制效果是最好的。

    1. QImage image = pixmap.toImage();
    2. QPixmap pixmap = QPixmap::fromImage(image);

    坐标平移:translate

    坐标旋转:rotate

    缩放:scaled

    状态保存 save

    状态恢复    restore

    恢复所有操作: resetTransform

    坐标

    物理坐标:

    视口坐标setviewport  默认情况下,视口等于绘图设备的整个矩形区。单位为像素

    逻辑坐标:

    窗口坐标,中心为原点(0,0)setwindow  如果想不用管实际物理坐标范围大小,可通过设置成窗口坐标来绘图。这是设备大小变化时,绘制的图片也自动变化大小。

    调用setwindow后,后面用到的坐标都是按逻辑坐标来算了的。是按比例缩放

    1. void Widget::paintEvent(QPaintEvent *event)
    2. {
    3. Q_UNUSED(event);
    4. QPainter painter(this);
    5. int W=width();
    6. int H=height();
    7. int side=qMin(W,H);//去长和宽的小值
    8. QRect rect((W-side)/2, (H-side)/2,side,side); //viewport矩形区
    9. painter.drawRect(rect); //Viewport大小
    10. painter.setViewport(rect);//设置Viewport
    11. painter.setWindow(-100,-100,200,200); // 设置窗口大小,逻辑坐标
    12. painter.setRenderHint(QPainter::Antialiasing);
    13. //设置画笔
    14. QPen pen;
    15. pen.setWidth(1); //线宽
    16. pen.setColor(Qt::red); //划线颜色
    17. //Qt::NoPen,Qt::SolidLine, Qt::DashLine, Qt::DotLine,Qt::DashDotLine,Qt::DashDotDotLine,Qt::CustomDashLine
    18. pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
    19. //Qt::FlatCap, Qt::SquareCap,Qt::RoundCap
    20. pen.setCapStyle(Qt::FlatCap);//线端点样式
    21. //Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin
    22. pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
    23. painter.setPen(pen);
    24. painter.setCompositionMode(QPainter::CompositionMode_Difference);
    25. for(int i=0; i<36;i++)
    26. {
    27. painter.drawEllipse(QPoint(50,0),50,50);
    28. painter.rotate(10);
    29. }
    30. }

    裁剪区域   setClipRegion

    延伸:设置widget的背景图片的办法

    1.在paintEvent事件中绘制图片

    1. void Widget::paintEvent(QPaintEvent * ev)
    2. {
    3. QPainter painter(this);
    4. painter.drawPixmap(rect(),QPixmap(":/bg.jpg"),QRect());
    5. }

    缺点就是要使用paintEvent事件需要新建一个类,不适合子窗口

    2.使用调色板QPalette来设置图片

    1. QPalette pal =this->palette();
    2. pal.setBrush(QPalette::Background,QBrush(QPixmap(":/bg.jpg")));
    3. setPalette(pal);

    3.使用样式表(setStyleSheet)

    setStyleSheet("border-image:url(:/bg.jpg)");


    项目经验1

    1.整个程序的大小通过sizeHint函数设置默认的大小,sizeHint为虚函数,可以重写重新设置大小。

    2.框架的widget重写resizeEvent函数(相当于mfc的onsize),调用height、width函数获取到高度、宽度。再通过setGeometry设置画图的区域widget的大小。

    3.画图的区域widget重写paintEvent函数。x、y轴都是按比例的画点,画线。(通过画图的区域的高度、宽度。数据的最大值、最小值和实时值。从而按比例算出x,y点坐标。)。

    项目经验2

    1.直接重写paintEvent函数,默认是视口坐标。即setviewport.  使用的坐标都是固定位置,就算窗口大小变化了,还是固定的。

    问题就是有部分图形可能会被遮挡,不会绘图。

    项目经验3

    直接重写paintEvent函数,但调用setwindow函数使用窗口坐标。这样窗口大小变化时,图形按比例进行缩放。

  • 相关阅读:
    【JVM面试题】JVM分代年龄为何是15次?能设置为16吗?
    Omapl38+国产FPGA开发板——开发案例使用测试资料说明(下)
    javaweb JAVA JSP学生信息档案管理系统JSP学生管理系统JSP学生档案管理系统JSP学生信息管理系统
    【Docker】Docker入门安装指南2022 (Windows版)
    性能指标>软硬件的性能指标
    多线程系列(一) -线程技术入门知识讲解
    UTF-8、Unicode编码与汉字的相关内容
    TAP 系列文章8 | TAP 学习中心——通过动手教程来学习
    基于粒子群优化算法的UAV三维路径规划研究付Matlab代码
    【零基础学Java】第二十篇 包装类3(Math,Arrays,System,BigInteger,BigDecimal,日期)
  • 原文地址:https://blog.csdn.net/baidu_16370559/article/details/128018621