小埋社区

    • 登录
    • 版块
    • 最新
    • 标签
    • 热门
    • 用户
    • 群组

    碰到个很神奇的问题,Qt计时器读数不准确

    编程
    c++ qt
    1
    1
    454
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • Bruce
      Bruce ACG 最后由 Bruce 编辑

      需要统计一个精确到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的误差

      1 条回复 最后回复 回复 引用 0
      • First post
        Last post
      © 2017-2023 小埋社区 All Rights Reserved | 皖ICP备17016228号-2