Как синхронизировать частоту обновления приложения и монитора в qt?

Я написал небольшое приложение на c ++ / qt, которое рисует самодельный курсор в реальной позиции курсора. Чтобы минимизировать задержку и соответственно смещение фактического положения курсора и нарисованного, мой QWidget обновляется как можно быстрее.

Часть конструктора:

QTimer *Timer = new QTimer(this);
connect(Timer, SIGNAL(timeout()), this, SLOT(update()));
Timer->start();

paintevent:

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;

}

Теперь у меня есть два вопроса:

  1. Продолжительность краски составляет около одной миллисекунды. Продолжительность одного цикла составляет от 10 до 15 миллисекунд. Что делает Qt между тем? Еще немного информации: нет разницы между update () и repaint (), и это не имеет значения, если я установлю таймер на целое число, например Timer->start(2); , Продолжительность цикла уменьшается из-за снижения разрешения монитора.

  2. Я использую монитор с частотой 60 Гц, поэтому мне не нужна более высокая частота обновления, если я смогу синхронизировать обновление с частотой обновления монитора. Это возможно? Я провел небольшое исследование по этому вопросу, но не нашел ничего действительно полезного.

Я надеюсь, что я не пропустил что-то фундаментальное. Буду благодарен за любой вклад.

Всего 1 ответ


Продолжительность одного цикла составляет от 10 до 15 миллисекунд. Что делает Qt между тем?

Скорее всего, он спит и / или имеет тенденцию заниматься другими делами, за которые отвечает цикл событий Qt. Обратите внимание, что в Windows по умолчанию для таймера процесса используется механизм низкого разрешения с гранулярностью 10 мс (и поэтому, если вы хотите, чтобы ваш процесс Windows мог спать менее 10 мс за раз, вам нужно вызвать timeBeginPeriod (1) в начале вашей программы).

синхронизировать обновление с частотой обновления монитора. Это возможно?

В принципе это возможно, но QWidget API Qt на самом деле не предназначен для такого уровня управления (QWidgets - это не столько API для игр / мультимедиа, сколько классический графический интерфейс для настольных приложений, поэтому он больше ориентирован на получение правильного контента, чем на гарантию максимально сжатых сроков). Если вы можете переключиться на использование QML вместо старого API QWidgets, QML имеет некоторую поддержку синхронизации с обновлением монитора. Другой возможностью было бы нарисовать вашу графику через OpenGL, внутри QOpenGLWindow ; класс QOpenGLWindow также имеет некоторую возможность синхронизации с частотой обновления (см. документацию по сигналу frameSwapped ()).

Кстати, обратите внимание, что запись вывода в stdout (aka std::cout ) и / или stderr (aka std::cerr ) может быть довольно медленной, и, делая это в своей опубликованной программе, вы, возможно, сильно отбрасываете измерения времени. Лучшим подходом было бы собрать данные о времени, но просто сохранить их внутри какой-то структуры данных до тех пор, пока вы не закончите измерение, а затем распечатать измеренные значения только в конце (например, когда вы выйдете из программы), чтобы распечатать значения не влияют на точность значений.


Есть идеи?

10000