Как синхронизировать c refre sh скорость приложения и монитора в qt? - PullRequest
0 голосов
/ 13 февраля 2020

Я написал небольшое приложение на c ++ / qt, в котором dr aws самостоятельно сделал курсор на фактической позиции курсора. Чтобы минимизировать задержку и соответственно смещение фактического положения курсора и нарисованного, мой 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 Гц, поэтому мне действительно не нужна более высокая частота повторения sh, если я смогу синхронизировать c обновление с refre sh скорость монитора. Это возможно? Я провел небольшое исследование по этому вопросу, но не нашел ничего действительно полезного.

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

1 Ответ

1 голос
/ 13 февраля 2020

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

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

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

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

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

...