qt中如何同步应用程序和显示器的刷新率?
How to sync the refresh rate of the application and the monitor in qt?
我写了一个小的 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;
}
现在我有两个问题:
绘画事件的持续时间约为一毫秒。一个周期的持续时间在 10 到 15 毫秒之间。与此同时,Qt 做了什么?更多信息: update() 和 repaint() 之间没有区别,如果我将计时器设置为固定整数,则没有区别,例如Timer->start(2);
。降低显示器的分辨率会缩短循环持续时间。
我使用的是 60 Hz 显示器,所以我真的不需要更高的刷新率,如果我能够将更新与显示器的刷新率同步的话。那可能吗?我对此做了一些研究,但我发现没有什么真正有用的。
我希望我没有遗漏一些基本的东西。如果有任何意见,我将不胜感激。
The duration of one cycle is between 10 and 15 milliseconds. What
does Qt do in the meantime?
很可能它在休眠,and/or 还倾向于 Qt 事件循环负责的其他业务。请注意,在 Windows 上,进程的计时器默认为具有 10 毫秒粒度的低分辨率机制(因此,如果您希望 Windows 进程能够一次休眠少于 10 毫秒,您我想在程序开始时调用 timeBeginPeriod(1))。
sync the update with the refresh rate of the monitor. Is that possible?
原则上这是可能的,但 Qt 的 QWidget API 并不是真正为该级别的控制而设计的(QWidgets 不是 gaming/multimedia API 而更多的是 classic 桌面应用程序 GUI,因此它更侧重于获取正确的内容,而不是保证最紧凑的时间)。如果你可以切换到使用 QML instead of the older QWidgets API, QML has for syncing-to-monitor-refresh. Another possibility would be to draw your graphics via OpenGL, inside a QOpenGLWindow; QOpenGLWindow class 也有一定的同步刷新率的能力(请参阅其 frameSwapped() 信号的文档)。
顺便说一下,将输出写入 stdout
(a.k.a. std::cout
) and/or stderr
(a.k.a std::cerr
) 可能会非常慢,并且通过在您发布的程序中这样做,您可能会大大偏离您的计时测量。更好的方法是收集计时数据,但只是将其存储在某种数据结构中,直到完成测量,然后仅在最后(例如,当您退出程序时)打印出测量值,以便打印值不影响值的准确性。
我写了一个小的 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;
}
现在我有两个问题:
绘画事件的持续时间约为一毫秒。一个周期的持续时间在 10 到 15 毫秒之间。与此同时,Qt 做了什么?更多信息: update() 和 repaint() 之间没有区别,如果我将计时器设置为固定整数,则没有区别,例如
Timer->start(2);
。降低显示器的分辨率会缩短循环持续时间。我使用的是 60 Hz 显示器,所以我真的不需要更高的刷新率,如果我能够将更新与显示器的刷新率同步的话。那可能吗?我对此做了一些研究,但我发现没有什么真正有用的。
我希望我没有遗漏一些基本的东西。如果有任何意见,我将不胜感激。
The duration of one cycle is between 10 and 15 milliseconds. What does Qt do in the meantime?
很可能它在休眠,and/or 还倾向于 Qt 事件循环负责的其他业务。请注意,在 Windows 上,进程的计时器默认为具有 10 毫秒粒度的低分辨率机制(因此,如果您希望 Windows 进程能够一次休眠少于 10 毫秒,您我想在程序开始时调用 timeBeginPeriod(1))。
sync the update with the refresh rate of the monitor. Is that possible?
原则上这是可能的,但 Qt 的 QWidget API 并不是真正为该级别的控制而设计的(QWidgets 不是 gaming/multimedia API 而更多的是 classic 桌面应用程序 GUI,因此它更侧重于获取正确的内容,而不是保证最紧凑的时间)。如果你可以切换到使用 QML instead of the older QWidgets API, QML has
顺便说一下,将输出写入 stdout
(a.k.a. std::cout
) and/or stderr
(a.k.a std::cerr
) 可能会非常慢,并且通过在您发布的程序中这样做,您可能会大大偏离您的计时测量。更好的方法是收集计时数据,但只是将其存储在某种数据结构中,直到完成测量,然后仅在最后(例如,当您退出程序时)打印出测量值,以便打印值不影响值的准确性。