Qt示例 | 2D Painting Example(二)

236 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

注:示例为Qt 5.1.1中的示例。
本文旨在剖析Qt示例的源码,总结函数使用方法以及编程思想,提高自己的编程能力。

示例运行效果:

1.gif

文件目录:

1653035707(1).jpg

具体实现:

Widget类:

1653297557(1).jpg

Widget类提供了一个基本的自定义小部件,用它来显示由Helper类绘制的简单动画。

除了构造函数之外,它只包含一个paintEvent()函数,以及一个实现动画的槽函数。一个Helper成员变量,和一个记录自上次更新以来所经过的时间的elapsed成员变量。

构造函数:

1653297972(1).jpg

构造函数用来初始化成员变量,保存Helper对象并调用Helper的构造函数,为小部件设置固定大小。

animate函数:

1653299224(1).jpg

这是一个定时器的槽函数,当一个计时器超时时,animate()槽函数将被调用。
这里,elapsed记录自计时器上次超时以来所经过的时间间隔,并在重新绘制小部件之前将其添加到现有值中。因为Helper类中使用的动画每秒钟循环一次,所以这里使用取余操作来确保消耗的变量总是小于1000。

paintEvent函数:

image.png

每次调用update()函数,都会出发paintEvent()函数,在paintEvent()函数中,调用Helper的paint()函数实现绘制事件。

beigin和end: 开始绘制绘制设备和绘制结束。

当创建无参的QPainter painter时,需要手动调用painter.begin(this)和painter.end();
当创建有参的QPainter painter(this)时,不需要手动调用painter.begin(this)和painter.end(),系统会自动调用。

setRenderHint(QPainter::Antialiasing): 反走样是图形学中的重要概念,用以防止通常所说的“锯齿”现象的出现。很多系统的绘图 API 里面都内置了有关反走样的算法,不过由于性能问题,默认一般是关闭的,Qt 也不例外。
通过这条语句,将Antialiasing属性设置为默认的true,就打开了QPainter的反走样功能,也就是抗锯齿。

GLWidget类:

image.png

GLWidget类中包含的函数和成员变量与Widget中的一样。

image.png GLWidget函数的实现与Widget中的也基本一样,相同的函数不做赘述。
构造函数中,多了一句代码:setAutoFillBackground(false);用来设置小部件背景是否自动填充。

GLWidget使用Helper类和Widget使用Helper类有一点区别,在GLWidget中Helper的构造函数会以指定QGL::SampleBuffers标志的格式调用。如果你的系统的OpenGL驱动支持这个功能,就可以启用抗锯齿。

Window类:

1653356624(1).jpg

Window类中包含一个将在所有小部件之间共享的Helper对象。

构造函数:

image.png

Window类中只有一个构造函数,在构造函数中完成了所有的工作:创建小部件,并将它们一起加入到布局中。
为了实现动画效果,创建一个50毫秒的计时器,并将溢出信号连接到Widget和GLWidget对象的animate()槽函数。定时器启动后,小部件会以每秒20帧左右的速度更新。

main函数:

1653038193(1).jpg

main函数的主要功能:

  1. 开启多重采样:设置多重采样数,从而使锯齿更加平滑,抗锯齿。缺省情况下,多重采样功能是关闭的。 多重采样是一种抗锯齿技术,它通过在一个像素上进行多次采样多次计算并最终汇总,可使绘制的图像边缘更加平滑。通过这种方式绘制出来的图片质量更高,显得更真实。

  2. 显示Window窗体。

到这里,2D Painting Example示例中的所有代码都介绍完了。基本框架就是Window中有一个Widget和一个GLWidget,在这两个Widget中调用Helper进行绘制。

一点思考:

  • 对于这个项目,因为它的绘图方法会同时用在两个不同的部件中,所以,这里将绘图方法单独封装成一个类。在主窗体中只创建一个,子窗体中调用。
  • 成员变量要初始化,放在构造函数中。
  • Q_DECL_OVERRIDE:写在虚函数后面,防止虚函数写错,例如参数类型错误等,在编译时会报编译错误信息。
  • 在实现这种永动效果的动画时,经常用到时间流逝这个概念,并定义"elapsed"变量来表示。项目里面的对时间取余方法用的非常好,可以保证数的范围在我们设定的区间内,不会越来越大,防止溢出。