Таймеры в Qt (и не только) позволяют выполнять некий код по заданным временным интервалам. Для таймеров существует два наиболее очевидных варианта использования. Рассмотрим соответствующие примеры.
Таймер для периодического выполнения действий
В первом случае таймер выступает в качестве альтернативы потокам. Преимуществом таймеров по сравнению с потоками является простота использования. Однако имеется и недостаток: код, вызываемый по таймеру, выполняется в главном потоке, что может привести к «подвисаниям» графического интерфейса пользователя.
Создадим виджет, который каждую секунду меняет цвет своего фона. Заголовочный файл timerdemowidget.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#ifndef TIMERDEMOWIDGET_H #define TIMERDEMOWIDGET_H #include <QWidget> #include <QTimer> class TimerDemoWidget : public QWidget { Q_OBJECT public: TimerDemoWidget( QWidget* parent = 0 ); ~TimerDemoWidget(); private slots: void setRandomBackgroundColor(); private: QTimer m_timer; }; #endif // TIMERDEMOWIDGET_H |
Реализация timerdemowidget.cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include "timerdemowidget.h" TimerDemoWidget::TimerDemoWidget( QWidget* parent ) : QWidget( parent ) { connect( &m_timer, SIGNAL( timeout() ), SLOT( setRandomBackgroundColor() ) ); m_timer.start( 1000 ); // Таймер будет срабатывать каждые 1000 миллисекунд, т.е. каждую секунду } TimerDemoWidget::~TimerDemoWidget() { } void TimerDemoWidget::setRandomBackgroundColor() { QPalette palette( this->palette() ); int r = qrand() % 256; int g = qrand() % 256; int b = qrand() % 256; palette.setColor( QPalette::Background, QColor( r, g, b ) ); setPalette( palette ); } |
Таймер запускается с помощью QTimer::start(). Остановить таймер можно вызовом QTimer::stop().
Для изменения цвета фона виджета используется объект палитры QPalette. Сам цвет QColor формируется из трех компонент r, g, b, выбранных случайным образом.
Осталось отобразить виджет:
1 2 3 4 5 6 7 8 9 10 11 |
#include <QApplication> #include "timerdemowidget.h" int main( int argc, char* argv[] ) { QApplication a( argc, argv ); TimerDemoWidget w; w.resize( 100, 100 ); w.show(); return a.exec(); } |
Похожий прием хорошо подходит для создания простых эффектов и анимации (например, мигающего текста или исчезающих кнопок).
Также этот вариант использования таймеров оказывается незаменимым в случае применения потоков из сторонних библиотек. В Qt сигнально-слотовая связь является потоково-безопасной, поэтому очередь передачи сообщений из рабочих потоков в главный уже имеется. Ситуация меняется, когда появляется поток, не генерирующий сигналов. В этом случае требуется вручную организовать такую очередь. Чтобы время от времени отслеживать состояние очереди и обновлять графический интерфейс пользователя, таймер и нужен.
Таймер для отложенного выполнения действия
QTimer хорошо подходит и в тех случаях, когда требуется выполнить действие всего один раз, но не сразу, а через некий временной интервал. Для этого предусмотрена функция-член QTimer::singleShot().
В следующем примере приводится код приложения, которое само завершается через 5 секунд после старта:
1 2 3 4 5 6 7 8 9 10 |
#include <QCoreApplication> #include <QTimer> int main( int argc, char* argv[] ) { QCoreApplication a( argc, argv ); QTimer::singleShot( 5000, &a, SLOT( quit() ) ); return a.exec(); } |
Аналогично можно реализовать любую функцию для выполнения отложенных действий. Например, можно создать исчезающую через некоторое время подсказку или организовать «спящий режим» для приложения в случае долгого отсутствия действий со стороны пользователя.