说明
使用 QCustomPlot 绘图库辅助开发时整理的学习笔记。同系列文章目录可见 《绘图库 QCustomPlot 学习笔记》目录。QCustomPlot 是开源项目,源码编写十分规范,想要理解它的可视化思路不算特别困难。我在这篇随笔中总结一下常用的源码修改技巧,下面的每一个技巧都是独立的,相互之间不会引发任何冲突。示例中使用的 QCustomPlot 版本号为 2.0.1
,但在更高的 2.x.x
版本中也适用。
1. 技巧一:启用 GPU 加速
这里选用 FreeGlut 库。
1.1 下载并编译 FreeGlut 库
去 https://freeglut.sourceforge.net/index.php 下载 freeglut 源码,编译出 freeglut 库,编译过程不做介绍。然后将编译出来的库以及 GL
文件夹下的五个头文件都包含进项目中,我使用的是 MSVC2015 64bit
静态库,因此在 pro/pri
文件中添加以下代码(因人而异):
HEADERS += \
$$PWD/GL/freeglut.h \
$$PWD/GL/freeglut_ext.h \
$$PWD/GL/freeglut_std.h \
$$PWD/GL/freeglut_ucall.h \
$$PWD/GL/glut.h
CONFIG(debug, debug | release) {
LIBS += -L$$PWD/lib64 -lfreeglut_staticd
LIBS += -L$$PWD/lib64 -lfreeglutd
}
CONFIG(release, debug | release) {
LIBS += -L$$PWD/lib64 -lfreeglut_static
LIBS += -L$$PWD/lib64 -lfreeglut
}
1.2 在 qcustomplot.cpp 文件中添加代码
在文件的前面几行(比如 #include "qcustomplot.h"
的后面)添加以下代码:
#define GLUT_DISABLE_ATEXIT_HACK
#include <GL/freeglut.h>
若同一个界面上有多个 QCustimPlot 窗口对象,且都开启了 GPU 加速,则在窗口切换时图形显示可能会出现错乱(被称为上下文异常),为了避免这种现象,需要在 QCPPaintBufferGlFbo::draw
函数里面添加以下代码:
/* inherits documentation from base class */
void QCPPaintBufferGlFbo::draw(QCPPainter *painter) const
{
if (!painter || !painter->isActive())
{
qDebug() << Q_FUNC_INFO << "invalid or inactive painter passed";
return;
}
if (!mGlFrameBuffer)
{
qDebug() << Q_FUNC_INFO << "OpenGL frame buffer object doesn't exist, reallocateBuffer was not called?";
return;
}
// 这个 if 语句是新添加的
if(QOpenGLContext::currentContext() != mGlContext.data())
{
mGlContext.data()->makeCurrent(mGlContext.data()->surface());
}
painter->drawImage(0, 0, mGlFrameBuffer->toImage());
}
1.3 在 pro 文件中添加代码
在 pro
文件中,添加以下代码:
QT += printsupport opengl
DEFINES += QCUSTOMPLOT_USE_OPENGL
这个 printsupport
是使用 QCustomPlot 时需要添加的,不论是否启用 GPU 加速都需要添加。后面的 opengl
则是为了启用 GPU 加速而新添的,此外,还需要使用 DEFINES
添加 QCUSTOMPLOT_USE_OPENGL
宏。
1.4 启用 GPU 加速
对 QCustomPlot 对象使用 setOpenGl()
函数设置是否启用 OpenGL,如下所示:
ui->Plot->setOpenGl(true);
可以通过 openGl()
函数的返回值判断是否成功启用了 GPU 加速:
qDebug() << "启用状态" << ui->Plot->openGl();
需要注意的是,当绘制的图形有大块填充区域,尤其是半透明的填充时,GPU 加速的效果才明显,这个时候才能减轻 CPU 压力。如果仅仅绘制一些简单的曲线图还开启 OpenGL,结果往往会适得其反,CPU 压力不减反增,有兴趣的可以进行测试,打开任务管理器观察启用前后 CPU 的占用百分比即可。
1.5 加速效果
绘制实时更新的、含有填充区域的图像,未开启 GPU 加速前的效果:
开启 GPU 加速后的效果:
以上演示例中并没有更改数据刷新频率(都为 10 ms 间隔)及数据量大小(都为 100 个点),两者仅有的差别为是否调用 setOpenGl(true)
开启了 GPU 加速。从结果中可以看到,开启 OpenGL 后,CPU 占用率从 16%~17% 下降到 7%~8%,GPU 占用率从 0% 上升到 41%~43%,并且从视觉效果上看,刷新变得更快了,这可能是因为 CPU 被减轻了压力,单次计算后显示所需时间更短了。
2. 技巧二:添加曲线平滑功能
思路是先计算贝塞尔控制点,然后使用 QPainterPath
绘制平滑曲线,参考资料:
2.1 在 qcustomplot.h 文件中添加代码
在原生的 class QCP_LIB_DECL QCPGraph
类定义中(使用搜索功能找到对应位置)添加以下两个内容,注意 public
与 protected
限定符:
class QCP_LIB_DECL QCPGraph : pu