qt中如何同步应用程序和显示器的刷新率?
Posted
技术标签:
【中文标题】qt中如何同步应用程序和显示器的刷新率?【英文标题】:How to sync the refresh rate of the application and the monitor in qt? 【发布时间】:2020-02-13 00:49:53 【问题描述】:我写了一个小 c++/qt 应用程序,在实际光标位置绘制一个自制光标。为了分别最小化实际光标位置和绘制的偏移量的延迟,我的 QWidget 尽可能快地自我更新。
部分构造函数:
QTimer *Timer = new QTimer(this);
connect(Timer, SIGNAL(timeout()), this, SLOT(update()));
Timer->start();
绘画事件:
void Widget::paintEvent(QPaintEvent* event)
auto t1 = std::chrono::high_resolution_clock::now();
std::cerr << "Duration Cycle: " << std::chrono::duration_cast<std::chrono::milliseconds>(t1 - LastT1).count() << std::endl;
LastT1 = t1;
// Draw Cursor
POINT LpPoint;
GetCursorPos(&LpPoint);
QPoint CursorPos(LpPoint.x, LpPoint.y);
CursorPos = mapFromGlobal(CursorPos);
QPainter Painter(this);
Painter.drawEllipse(CursorPos, 20, 20);
std::cerr << "Duration Paintevent: " << std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - t1).count() << std::endl;
现在我有两个问题:
paintevent 的持续时间约为一毫秒。一个周期的持续时间在 10 到 15 毫秒之间。 Qt 在此期间做了什么?更多信息: update() 和 repaint() 之间没有区别,如果我将计时器设置为固定整数,例如Timer->start(2);
。降低显示器的分辨率会缩短循环持续时间。
我使用的是 60 Hz 显示器,所以如果我能够将更新与显示器的刷新率同步,我真的不需要更高的刷新率。那可能吗?我对此进行了一些研究,但没有发现任何真正有用的东西。
我希望我没有错过一些基本的东西。我会感谢任何意见。
【问题讨论】:
【参考方案1】:一个周期的持续时间在 10 到 15 毫秒之间。什么 Qt同时做了吗?
它很可能处于休眠状态,和/或还倾向于 Qt 事件循环负责的其他业务。请注意,在 Windows 上,进程的计时器默认为具有 10mS 粒度的低分辨率机制(因此,如果您希望 Windows 进程一次能够休眠少于 10mS,您需要调用 timeBeginPeriod(1) at程序的开始)。
将更新与显示器的刷新率同步。那可能吗?
原则上这是可能的,但 Qt 的 QWidget API 并不是真正为那种级别的控制而设计的(QWidgets 与其说是一个游戏/多媒体 API,不如说是一个经典的桌面应用程序 GUI,所以它更侧重于获取内容正确,而不是保证最紧迫的时间)。如果您可以切换到使用 QML 而不是旧的 QWidgets API,QML 有 some support 用于同步到监视器刷新。另一种可能性是通过 OpenGL 在 QOpenGLWindow 内绘制图形; QOpenGLWindow 类还具有与刷新率同步的能力(有关其 frameSwapped() 信号,请参阅文档)。
顺便说一句,将输出写入stdout
(又名std::cout
)和/或stderr
(又名std::cerr
)可能会非常慢,并且在您发布的程序中这样做可能会浪费您的时间测量了很多。更好的方法是收集计时数据,但只是将其存储在某种数据结构中,直到您完成测量,然后仅在最后(例如,当您退出程序时)打印出测量值,以便打印值不会影响值的准确性。
【讨论】:
以上是关于qt中如何同步应用程序和显示器的刷新率?的主要内容,如果未能解决你的问题,请参考以下文章
[android数据库同步]架构一种Android界面数据同步刷新机制