TimerEvent在Windows和Mac上具有不同的速度

时间:2018-04-03 22:17:11

标签: c++ qt timer cross-platform qtimer

我的QT应用程序依赖于TimerEvent(startTimer / killTimer)来动画GUI组件。然而,最近,我在我的Mac笔记本电脑上编译并运行了我的应用程序(而不是我正在开发的Windows桌面计算机),并发现现在一切似乎都以通常的速度运行/更新速度的一半。

应用程序并不滞后,只是看起来更新率低于最初的更新率。我该怎么做才能保证在所有平台上与应用程序保持一致的时间安排?

或者,我应该为临时计时器事件使用不同的功能吗?我不愿意,因为TimerEvent将更新周期集成到Widgets中是非常方便的,但是如果它们提供一致的时序则会感兴趣。

(上下文的基本示例代码):

// Once MyObject is created, counts to 20. 
// The time taken is noticeably different on each platform though.

class MyObject: public QObject {

public:
  MyObject() {
    timerId = startTimer(60);
  }

protected:
  void timerEvent(QTimerEvent* event) {
    qDebug() << (counter++);
    if(counter == 20) {
       killTimer(timerId);
    }
    Object::timerEvent(event);
  }

private:
  int timerId = -1, counter = 0;
}

1 个答案:

答案 0 :(得分:4)

由于准确性,您可能会发现问题。 QTimer's accuracy varies on different platforms

  

请注意,QTimer的准确性取决于底层操作系统和硬件。 timerType参数允许您自定义计时器的准确性。有关不同计时器类型的信息,请参阅Qt :: TimerType。大多数平台支持20毫秒的精度;一些提供更多。如果Qt无法提供所请求的计时器事件数,它将默默地丢弃一些。

您可以尝试将Qt::PreciseTimer传递给startTimer(默认值为Qt::CoarseTimer),但我还建议您针对某个开始时间或上一个时间戳的时间戳检查当前时间戳。这将允许您调整处理计时器事件之间不同时间量的方式。这与how time steps are sometimes handled in games没有什么不同。

例如:

class MyObject: public QObject {

public:
  MyObject() {
    timerId = startTimer(60, Qt::PreciseTimer);
    startTime = std::chrono::steady_clock::now();
  }

protected:
  void timerEvent(QTimerEvent* event) {
    qDebug() << (counter++);
    if(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - startTime) / 60 >= 20) {
       killTimer(timerId);
    }
    Object::timerEvent(event);
  }

private:
  int timerId = -1, counter = 0;
  std::chrono::steady_clock::time_point startTime;
}

使用QElapsedTimer的另一个例子:

class MyObject: public QObject {

public:
  MyObject() {
    timerId = startTimer(60, Qt::PreciseTimer);
    elapsedTimer.start();
  }

protected:
  void timerEvent(QTimerEvent* event) {
    qDebug() << (counter++);
    if(elapsedTimer.elapsed() / 60 >= 20) {
       killTimer(timerId);
    }
    Object::timerEvent(event);
  }

private:
  int timerId = -1, counter = 0;
  QElapsedTimer elapsedTimer;
}