Если пользователь щелкает по этому виджету, мы находим ближайшую метку, используя тонкую, но эффективную математическую формулу, а результат идет на установку новой продолжительности таймера. Затем мы генерируем событие перерисовки. Метка, по которой щелкнул пользователь, теперь будет располагаться сверху поворотного диска и будет поворачиваться против часовой стрелки до тех пор, пока не будет достигнуто значение 0.
устанавливаем область отображения на максимальный квадрат, который можно разместить внутри виджета, и мы устанавливаем окно на прямоугольник (—50, —50, 100, 100), то есть на прямоугольник с размерами 100 × 100, который покрывает пространство от точки (—50, —50) до точки (+50, +50). Шаблонная функция qMin возвращает наименьшее из двух значений аргументов. Затем мы вызываем функцию draw для фактического вывода рисунка на экран.
Рис. 8.10. Вид виджета OvenTimer при трех различных размерах.
Если область отображения не была бы квадратом, таймер духовки принял бы форму эллипса, когда форма виджета перестанет быть квадратной после изменения его размеров. Чтобы избежать такой деформации, мы должны устанавливать область отображения и окно на прямоугольник с одинаковым соотношением сторон.
Теперь давайте рассмотрим программный код рисования:
Мы начинаем с отображения маленького треугольника в позиции 0 в верхней части виджета. Этот треугольник задается в программе тремя фиксированными координатами, и мы используем функцию drawPolygon для его воспроизведения.
Одно из удобств применения механизма «окно—область отображения» заключается в том, что мы можем при программировании в командах рисования жестко задавать координаты точек и тем не менее добиваться необходимого изменения размеров.
16 QConicalGradient coneGradient(0, 0, -90.0);
17 coneGradient.setColorAt(0.0, Qt::darkGray);
18 coneGradient.setColorAt(0.2, niceBlue);
19 coneGradient.setColorAt(0.5, Qt::white);
20 coneGradient.setColorAt(1.0, Qt::darkGray);
21 painter->setBrush(coneGradient);
22 painter->drawEllipse(-46, -46, 92, 92);
Мы
рисуем внешнюю окружность и заполняем ее, используя конический градиент. Центр градиента находится в точке (0, 0), а его угол равен —90°.
23 QRadialGradient haloGradient(0, 0, 20, 0, 0);
24 haloGradient.setColorAt(0.0, Qt::lightGray);
25 haloGradient.setColorAt(0.8, Qt::darkGray);
26 haloGradient.setColorAt(0.9, Qt::white);
27 haloGradient.setColorAt(1.0, Qt::black);
28 painter->setPen(Qt::NoPen);
29 painter->setBrush(haloGradient);
30 painter->drawEllipse(-20, -20, 40, 40);
Мы заполняем внутреннюю окружность, используя радиальный градиент. Центр и фокус градиента располагаются в точке (0, 0). Радиус градиента равен 20.
Мы вызываем функцию rotate для поворота системы координат рисовальщика. В старой системе координат нулевая отметка находилась сверху; теперь нулевая отметка перемещается для установки соответствующего времени, которое остается до срабатывания таймера. После каждого поворота мы снова рисуем ручку таймера, поскольку его ориентация зависит от угла поворота.