持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情
注:示例为Qt 5.1.1中的示例。
本文旨在剖析Qt示例的源码,总结函数使用方法以及编程思想,提高自己的编程能力。
示例运行效果:
文件目录:
具体实现:
Widget类:
Widget类提供了一个基本的自定义小部件,用它来显示由Helper类绘制的简单动画。
除了构造函数之外,它只包含一个paintEvent()函数,以及一个实现动画的槽函数。一个Helper成员变量,和一个记录自上次更新以来所经过的时间的elapsed成员变量。
构造函数:
构造函数用来初始化成员变量,保存Helper对象并调用Helper的构造函数,为小部件设置固定大小。
animate函数:
这是一个定时器的槽函数,当一个计时器超时时,animate()槽函数将被调用。
这里,elapsed记录自计时器上次超时以来所经过的时间间隔,并在重新绘制小部件之前将其添加到现有值中。因为Helper类中使用的动画每秒钟循环一次,所以这里使用取余操作来确保消耗的变量总是小于1000。
paintEvent函数:
每次调用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类:
GLWidget类中包含的函数和成员变量与Widget中的一样。
GLWidget函数的实现与Widget中的也基本一样,相同的函数不做赘述。
构造函数中,多了一句代码:setAutoFillBackground(false);用来设置小部件背景是否自动填充。
GLWidget使用Helper类和Widget使用Helper类有一点区别,在GLWidget中Helper的构造函数会以指定QGL::SampleBuffers标志的格式调用。如果你的系统的OpenGL驱动支持这个功能,就可以启用抗锯齿。
Window类:
Window类中包含一个将在所有小部件之间共享的Helper对象。
构造函数:
Window类中只有一个构造函数,在构造函数中完成了所有的工作:创建小部件,并将它们一起加入到布局中。
为了实现动画效果,创建一个50毫秒的计时器,并将溢出信号连接到Widget和GLWidget对象的animate()槽函数。定时器启动后,小部件会以每秒20帧左右的速度更新。
main函数:
main函数的主要功能:
-
开启多重采样:设置多重采样数,从而使锯齿更加平滑,抗锯齿。缺省情况下,多重采样功能是关闭的。 多重采样是一种抗锯齿技术,它通过在一个像素上进行多次采样多次计算并最终汇总,可使绘制的图像边缘更加平滑。通过这种方式绘制出来的图片质量更高,显得更真实。
-
显示Window窗体。
到这里,2D Painting Example示例中的所有代码都介绍完了。基本框架就是Window中有一个Widget和一个GLWidget,在这两个Widget中调用Helper进行绘制。
一点思考:
- 对于这个项目,因为它的绘图方法会同时用在两个不同的部件中,所以,这里将绘图方法单独封装成一个类。在主窗体中只创建一个,子窗体中调用。
- 成员变量要初始化,放在构造函数中。
- Q_DECL_OVERRIDE:写在虚函数后面,防止虚函数写错,例如参数类型错误等,在编译时会报编译错误信息。
- 在实现这种永动效果的动画时,经常用到时间流逝这个概念,并定义"elapsed"变量来表示。项目里面的对时间取余方法用的非常好,可以保证数的范围在我们设定的区间内,不会越来越大,防止溢出。