碰到个很神奇的问题,Qt计时器读数不准确
-
需要统计一个精确到1ms的时间
一开始我用的是QTimer
类,间隔1ms让一个整形量自增1,结果发现QTimer
效率还是太低,虽然可以精确到毫秒,但是没法准确控制间隔为1ms,具体来说平均间隔大约为1.2ms。
不过后来我发现这个量没必要由我自己去维护,Qt内置了QElapsedTimer
类,专门用来计时,可以精确到μs,使用elapsed()
方法直接获取start()
开始计时后经过的毫秒数。最终测试结果确实比较准确,平均间隔可以达到1.0ms。
不过我录了一个120FPS的视频逐帧分析后发现,这个读数的尾数浮动其实非常大,理论上120FPS的视频每帧间隔是8.33ms,但是用elapsed()
方法获取到的整形值的间隔却是4-11,浮动高达大约50%。理论上可以精确到μs的计时器不可能在ms数量级上产生这么大的误差啊...
虽然有可能是GUI绘制耗时产生的误差,但是原来使用QTimer
时也没遇到这么大的误差。
显示当前经过毫秒的源代码如下
#include "msecsgetter.h" #include "ui_msecsgetter.h" #include <QDateTime> //定义重绘GUI的间隔,单位ms #define INTERVAL 4 MSecsGetter::MSecsGetter(QWidget *parent) : QWidget(parent) , ui(new Ui::MSecsGetter) { ui->setupUi(this); timer = new QTimer(this); //定时器,用来定时触发重绘GUI tick = new QElapsedTimer(); //计时器,用来记录经过的毫秒数 //当计时器完成一次计时后,将GUI上的label内数字重绘为当前经过的毫秒数 connect(timer, &QTimer::timeout, [=]() { ui->label->setText(QString::number(startTime + tick->elapsed())); }); startTime = QDateTime::currentMSecsSinceEpoch(); //以自1970-01-01 00:00:00经过的毫秒数为初值 //启动定时器和计时器 tick->start(); timer->start(INTERVAL); } MSecsGetter::~MSecsGetter() { delete ui; }
后续:找到问题原因了,GUI重绘间隔的问题,把间隔调成1就好了,不过因为GUI重绘比较耗时(至少比让一个整形自增费时),所以会有约1ms的误差