Я написал небольшое приложение, которое заменяет курсор нарисованным от руки курсором. Для этого я использовал QOpenGlWidget. Для анимации я использую сигнал frameSwapped:
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
До сих пор я не использую какую-либо конкретную c функцию OpenGl, поэтому я просто переопределяю аналог paintevent на classi c QWidget.
Документация Qt :
При выполнении рисования только с использованием QPainter рисование также можно выполнить так же, как это делается для обычных виджетов: переопределив paintEvent ().
void Widget::paintEvent(QPaintEvent* event) {
// Draw Cursor
POINT LpPoint;
GetCursorPos(&LpPoint);
QPoint CursorPos(LpPoint.x, LpPoint.y);
CursorPos = mapFromGlobal(CursorPos);
QPainter Painter(this);
Painter.drawEllipse(CursorPos, 20, 20);
}
Я снял результат с 240 кадрами в секунду и понял, что мой нарисованный курсор находится на 2 кадра за курсором windows. Неважно, что лагов вообще нет. Но был бы хорош только один кадр. И было бы здорово, если бы я мог количественно определить отставание. Так что я знаю, что это один кадр + - продолжительность рендеринга. Я уже прочитал это , но я не совсем знаком с OpenGl. И я не думаю, что смогу использовать это с QOpenGlWidget. Может быть, у кого-то есть идея, как уменьшить задержку до одного кадра.
Обновление 1 : Я провел небольшое исследование и много пытался с умеренным успехом. Моя последняя версия:
connect(this, SIGNAL(frameSwapped()), this, SLOT(animate()));
void Widget::animate() {
makeCurrent();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glFinish();
//std::this_thread::sleep_for(std::chrono::milliseconds(12));
update();
}
Я использую glFini sh () для синхронизации c CPU и GPU. Теперь нарисованный курсор находится примерно на один кадр позади. Иногда это даже лучше, чем один кадр. Но есть пропущенные кадры, поэтому нарисованный курсор вообще не двигается. В целом нет согласованности. У меня все еще есть некоторые проблемы с пониманием того, как именно обновляется OpenGl. Может быть, немного больше информации: setIntervall
установлен в 1, и это с двойной буферизацией. Я думаю, может быть, это проблема, не знаю, что именно делает Qt. Вызов update
только планирует обновление, и я не могу контролировать, как буферы переставляются. Может быть, у кого-то есть больше опыта по этим вопросам. Я могу сказать, что paintevent / paintGL вызывается каждые 16 мс. Я добавил std::this_thread::sleep_for(std::chrono::milliseconds(12));
, чтобы уменьшить задержку между рендером и фактическим положением мыши. Это помогает уменьшить среднюю задержку. Но для меня почти невозможно сделать прогноз solid о том, что произойдет в следующем кадре.
Обновление 2: Я опубликовал похожую проблему на Qt forum . Хотя это и не прямой ответ, он содержит некоторую полезную информацию.