Функция
01 void OvenTimer::mousePressEvent(QMouseEvent *event)
02 {
03 QPointF point = event->pos - rect.center;
04 double theta = atan2(-point.x, -point.y) * 180 / 3.14159265359;
05 setDuration(duration + int(theta / DegreesPerSecond));
06 update;
07 }
Если пользователь щелкает по этому виджету, мы находим ближайшую метку, используя тонкую, но эффективную математическую формулу, а результат идет на установку новой продолжительности таймера. Затем мы генерируем событие перерисовки. Метка, по которой щелкнул пользователь, теперь будет располагаться сверху поворотного диска и будет поворачиваться против часовой стрелки до тех пор, пока не будет достигнуто значение 0.
01 void OvenTimer::paintEvent(QPaintEvent * /* event */)
02 {
03 QPainter painter(this);
04 painter.setRenderHint(QPainter::Antialiasing, true);
05 int side = qMin(width, height);
06 painter.setViewport((width - side) / 2, (height - side) / 2,
07 side, side);
08 painter.setWindow(-50, -50, 100, 100);
09 draw(&painter);
10 }
B
Если область отображения не была бы квадратом, таймер духовки принял бы форму эллипса, когда форма виджета перестанет быть квадратной после изменения его размеров. Чтобы избежать такой деформации, мы должны устанавливать область отображения и окно на прямоугольник с одинаковым соотношением сторон.
Теперь давайте рассмотрим программный код рисования:
01 void OvenTimer::draw(QPainter *painter)
02 {
03 static const int triangle[3][2] = {
04 { -2, -49 }, { +2, -49 }, { 0, -47 }
05 };
10 QPen thickPen(palette.foreground, 1.5);
11 QPen thinPen(palette.foreground, 0.5);
12 QColor niceBlue(150, 150, 200);
13 painter->setPen(thinPen);
14 painter->setBrush(palette.foreground);
15 painter->drawPolygon(QPolygon(3, ▵[0][0]));
Мы начинаем с отображения маленького треугольника в позиции 0 в верхней части виджета. Этот треугольник задается в программе тремя фиксированными координатами, и мы используем функцию
Одно из удобств применения механизма «окно—область отображения» заключается в том, что мы можем при программировании в командах рисования жестко задавать координаты точек и тем не менее добиваться необходимого изменения размеров.
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);