03 Ticker::Ticker(QWidget *parent)
04 : QWidget(parent)
05 {
06 offset = 0;
07 myTimerId = 0;
08 }
Конструктор инициализирует смещение offset значением 0. Координата x начала вывода текста рассчитывается на основе значения offset. Таймер всегда имеет ненулевой идентификатор, поэтому мы используем 0, показывая, что таймер еще не запущен.
09 void Ticker::setText(const QString &newText)
10 {
11 myText = newText;
12 update();
13 updateGeometry();
14 }
Функция setText() ycтaнaвливaeт oтoбpaжaeмый тeкcт. Oнa вызывaeт update() для выдачи запроса на перерисовку и updateGeometry() для уведомления всех менеджеров компоновки, содержащих виджет Ticker, об изменении идеального размера.
15 QSizeTicker::sizeHint() const
16 {
17 return fontMetrics().size(0, text());
18 }
Функция sizeHint() возвращает в качестве идеального размера виджета размеры области, занимаемой текстом. Функция QWidget::fontMetrics() возвращает объект QFontMetrics, который можно использовать для получения информации относительно шрифта виджета. В данном случае мы определяем размер заданного текста. (В первом аргументе функции QFontMetrics::size() задается флажок, который не нужен для простых строк, поэтому мы просто передаем 0.)
19 void Ticker::paintEvent(QPaintEvent * /* event */)
20 {
21 QPainter painter(this);
22 int textWidth = fontMetrics().width(text());
23 if (textWidth < 1)
24 return;
25 int х= -offset;
26 while (x < width()) {
27 painter.drawText(x, 0, textWidth, height(),
28 Qt::AlignLeft | Qt::AlignVCenter, text());
29 x += textWidth;
30 }
31 }
Функция paintEvent() отображает текст при помощи функции QPainter::drawText(). Она использует функцию fontMetrics() для определения размера области, занимаемой текстом по горизонтали, и затем выводит текст столько раз, сколько необходимо для заполнения виджета по всей его ширине, учитывая значение смещения offset.
32 void Ticker::showEvent(QShowEvent * /* event */)
33 {
34 myTimerId = startTimer(30);
35 }
функция showEvent() запускает таймер. Вызов QObject::startTimer() возвращает число—идентификатор, которое мы можем использовать позже для идентификации таймера. QObject поддерживает несколько независимых таймеров, каждый из которых использует свой временной интервал. После вызова функции startTimer() Qt генерирует событие таймера приблизительно через каждые 30 миллисекунд, причем точность зависит от базовой операционной системы.
Мы могли бы функцию startTimer() вызвать в конструкторе Ticker, но мы экономим некоторые ресурсы за счет генерации Qt событий таймера только в тех случаях, когда виджет действительно видим.
36 void Ticker::timerEvent(QTimerEvent *event)
37 {
38 if (event->timerId() == myTimerId) {
39 ++offset;
40 if (offset >= fontMetrics().width(text()))
41 offset= 0;
42 scroll(-1, 0);
43 } else {
44 QWidget::timerEvent(event);
45 }
46 }
Функция timerEvent() вызывается системой в соответствующие моменты времени. Она увеличивает смещение offset на 1 для имитации движения по всей области вывода текста. Затем она перемещает содержимое виджета на один пиксель влево при помощи фyнкции QWidget::scroll(). Вполне достаточно было бы вызывать функцию update() вместо scroll(), но вызов функции scroll() более эффективен, потому что она просто перемещает существующие на экране пиксели и генерирует событие рисования для открывшейся области виджета (которая в данном случае представляет собой полосу шириной в один пиксель).
Если событие таймера не относится к нашему таймеру, мы передаем его дальше в наш базовый класс.