Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Система рисования. Печать _ Начало работы с 2D графикой

Автор: Cergey 8.7.2009, 18:36

Здравствуйте!

Наверняка при изучении работы с 2D гдафикой видели следующий пример:

Раскрывающийся текст
void OvenTimer::draw(QPainter *painter) 
{
  static const QCOORD triangle[3][2] = {
      { -2, -49 }, { +2, -49 }, { 0, -47 }
  };
  QPen thickPen(colorGroup().foreground(), 2);
  QPen thinPen(colorGroup().foreground(), 1);
  
  painter->setPen(thinPen);
  painter->setBrush(colorGroup().foreground());
  painter->drawConvexPolygon(QPointArray(3, &triangle[0][0]));


Рисование виджета начинается с маленького треугольника, который обозначает нулевую позицию вверху. Треугольник задается тремя, жестко зашитыми парами координат. Собственно рисование производится функцией drawConvexPolygon(). Треугольник можно было бы нарисовать функцией drawPolygon(), но если заранее известно, что многоугольник выпуклый, то вы можете сэкономить несколько микросекунд, за счет использования функции drawConvexPolygon().

Одна из замечательных сторон механизма перехода от логических координат к физическим состоит в том, что мы можем жестко зашивать координаты точек в исходный код и при этом получать неплохие результаты, при изменении размеров виджета.
  painter->setPen(thickPen); 
  painter->setBrush(colorGroup().light());
  painter->drawEllipse(-46, -46, 92, 92);
  painter->setBrush(colorGroup().mid());
  painter->drawEllipse(-20, -20, 40, 40);
  painter->drawEllipse(-15, -15, 30, 30);


Далее рисуются внешний и два внутренних круга. Внешний круг заполняется цветом "light" (обычно -- белый), Внутренние круги заполняются цветом "mid" (обычно -- серый).
  int secs = duration(); 
  painter->rotate(secs * DegreesPerSecond);
  painter->drawRect(-8, -25, 16, 50);
  
  for (int i = 0; i <= MaxMinutes; ++i) {
    if (i % 5 == 0) {
      painter->setPen(thickPen);
      painter->drawLine(0, -41, 0, -44);
      painter->drawText(-15, -41, 30, 25,
                        AlignHCenter | AlignTop,
                        QString::number(i));
      } else {
        painter->setPen(thinPen);
        painter->drawLine(0, -42, 0, -44);
      }
      painter->rotate(-DegreesPerMinute);
  }
}


Затем рисуются рукоятка и риски на лимбе. Напротив каждой пятой риски рисуется число, обозначающее количество минут. Функция rotate() вызывается для того, чтобы повернуть систему координат. В начальный момент, риска с отметкой "0" находилась вверху, теперь же она переместилась в точку, координаты которой зависят от оставшегося до срабатывания времени. Рукоятка рисуется после выполнения поворота, поскольку ее ориентация зависит от угла поворота.

В цикле for, по краю внешнего круга рисуются риски, а под ними -- числа, обозначающие количество минут, с шагом 5. В конце каждой итерации выполняется поворот системы координат по часовой стрелке на 7 градусов, что соответствует одной минуте. Таким образом, каждая следующая риска будет рисоваться на своем месте, хотя координаты в drawLine() и drawText() задаются одни и те же.
Это про таймер электропечи.

Мне не понятно
  
int secs = duration();
  painter->rotate(secs * DegreesPerSecond);
  painter->drawRect(-8, -25, 16, 50);
  
  for (int i = 0; i <= MaxMinutes; ++i) {
    if (i % 5 == 0) {
      painter->setPen(thickPen);
      painter->drawLine(0, -41, 0, -44);
      painter->drawText(-15, -41, 30, 25,
                        AlignHCenter | AlignTop,
                        QString::number(i));
      } else {
        painter->setPen(thinPen);
        painter->drawLine(0, -42, 0, -44);
      }
      painter->rotate(-DegreesPerMinute);
  }
}

У Жасмин Бланшет написано про это:
Сначала там поворачивают систему координат рисовальщика против часовой стрелки, затем рисуют рукоятку, а затем поворачивают рисовальщик по часовой стрелке и поэтому в цикле не надо изменять координаты в drawLine.

Но ведь используется одна функция - rotate. Где не искал, везде ничего не исправлено.
Если это правильно, может кто нибудь пожалуйста это объяснить!!!

Автор: Litkevich Yuriy 8.7.2009, 20:34

Цитата(Cergey @ 8.7.2009, 22:36) *
Сначала там поворачивают систему координат рисовальщика против часовой стрелки, затем рисуют рукоятку, а затем поворачивают рисовальщик по часовой стрелке и поэтому в цикле не надо изменять координаты в drawLine.
Я с этим примером не разбирался, но такого утверждения из приведённого тобой описания выше не вижу. А вижу только это:
Цитата(Cergey @ 8.7.2009, 22:36) *
Одна из замечательных сторон механизма перехода от логических координат к физическим состоит в том, что мы можем жестко зашивать координаты точек в исходный код
Цитата(Cergey @ 8.7.2009, 22:36) *
В конце каждой итерации выполняется поворот системы координат по часовой стрелке на 7 градусов, что соответствует одной минуте. Таким образом, каждая следующая риска будет рисоваться на своем месте, хотя координаты в drawLine() и drawText() задаются одни и те же.
Т.е. в функцию drawLine() передаются абсолютные координаты, затем рисовальщик поворачивается - поворот один.

Автор: Cergey 8.7.2009, 21:23

Если передаются абсолютные координаты, то первый поворот ничего не меняет, тогда всегда одинаковое изображение. Может тут все-таки ошибка???

Автор: Litkevich Yuriy 8.7.2009, 21:53

Цитата(Cergey @ 9.7.2009, 1:23) *
Может тут все-таки ошибка???
ну это легко проверить, скомпилируй пример, будет ли он работать как описано?

Цитата(Cergey @ 9.7.2009, 1:23) *
то первый поворот ничего не меняет,
как так? картинка-то поворачивается.

Автор: Cergey 9.7.2009, 8:36

Цитата(Litkevich Yuriy @ 8.7.2009, 22:53) *
как так? картинка-то поворачивается.

Система координат если абсолютная???

Автор: Litkevich Yuriy 9.7.2009, 14:24

это дело можно представить себе так:
Есть стол, на нём лист бумаги. когда рисуем штрихи и цифирки, то используются абсолютные координаты стола, а поворот осуществляем только листа, относительно его предыдущего положения.

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)