Таймеры
QObject, базовый класс всех объектов Qt, предоставляет базовую поддержку таймеров в Qt. С помощью QObject::startTimer() вы запускаете таймер с интервалом в миллисекундах в качестве аргумента. Функция возвращает уникальный идентификатор таймера. Таймер будет срабатывать с заданным интервалом до тех пор, пока вы явно не вызовете QObject::killTimer() с идентификатором таймера.
Для работы этого механизма приложение должно работать в цикле событий. Вы запускаете цикл событий с помощью QApplication::exec(). Когда таймер срабатывает, приложение отправляет событие QTimerEvent, и поток управления выходит из цикла событий, пока событие таймера не будет обработано. Это означает, что таймер не может сработать, пока ваше приложение занято выполнением других задач. Другими словами: точность таймеров зависит от гранулярности вашего приложения.
В многопоточных приложениях вы можете использовать механизм таймеров в любом потоке, имеющем цикл событий. Чтобы запустить цикл событий из потока, не связанного с графическим интерфейсом, используйте QThread::exec(). Qt использует аффинити потока объекта thread affinity для определения, какой поток будет доставлять событие QTimerEvent. По этой причине вы должны запускать и останавливать все таймеры в потоке объекта; запуск таймеров для объектов в другом потоке невозможен.
Верхний предел значения интервала определяется количеством миллисекунд, которое может быть указано в целом числе со знаком (на практике это период чуть более 24 дней). Точность зависит от базовой операционной системы. В Windows 2000 точность составляет 15 миллисекунд; другие системы, которые мы тестировали, могут обрабатывать интервалы в 1 миллисекунду.
Основной API для функциональности таймеров — QTimer. Этот класс предоставляет регулярные таймеры, которые излучают сигнал при срабатывании таймера, и наследует QObject, чтобы хорошо вписаться в структуру владения большинства программ с графическим интерфейсом. Обычный способ его использования выглядит так:
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &Foo::updateCaption);
timer->start(1000); Объект QTimer делается дочерним по отношению к этому виджету, поэтому при удалении этого виджета удаляется и таймер. Далее, его сигнал timeout() подключается к слоту, который будет выполнять работу, и он запускается со значением 1000 миллисекунд, что означает, что он будет срабатывать каждую секунду.
QTimer также предоставляет статическую функцию для одноразовых таймеров. Например:
QTimer::singleShot(200, this, &Foo::updateCaption);
Через 200 миллисекунд (0,2 секунды) после выполнения этой строки кода, будет вызван updateCaption() слот.
Для работы QTimer необходимо иметь цикл событий в вашем приложении; то есть, вы должны где-то вызвать QCoreApplication::exec(). События таймеров будут доставляться только во время работы цикла событий.
В многопоточных приложениях вы можете использовать QTimer в любом потоке, имеющем цикл событий. Чтобы запустить цикл событий из потока, не связанного с графическим интерфейсом, используйте QThread::exec(). Qt использует аффинити таймера thread affinity для определения, какой поток будет излучать сигнал timeout(). Поэтому вы должны запускать и останавливать таймер в его потоке; запуск таймера из другого потока невозможен.
Пример Аналоговые часы демонстрирует, как использовать QTimer для перерисовки виджета с заданным интервалом. Из реализации примера AnalogClock:
AnalogClock::AnalogClock(QWidget *parent)
: QWidget(parent)
{
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, QOverload<>::of(&AnalogClock::update));
timer->start(1000);
...
} Каждую секунду QTimer будет вызывать слот QWidget::update() для обновления отображения часов.
Если у вас уже есть подкласс QObject и вам нужна простая оптимизация, вы можете использовать QBasicTimer вместо QTimer. При использовании QBasicTimer необходимо переопределить timerEvent() в вашем подклассе QObject и обработать таймаут там. Пример Wiggly показывает, как использовать QBasicTimer.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.15/timers.html