Рис. 5.3. Вычерчивание линии при помощи QPainter.
Перед вызовом в QPainter функции drawLine мы устанавливаем цвет линии, используя функцию setPen. Мы могли бы жестко запрограммировать цвет (например, черный или серый), но лучше использовать палитру виджета.
Каждый виджет имеет палитру, которая определяет назначение цветов. Например, предусмотрен цвет фона виджетов (обычно светло—серый) и цвет текста на этом фоне (обычно черный). По умолчанию палитра виджета адаптирована под схему цветов оконной системы. Используя цвета из палитры, мы обеспечим в IconEditor учет пользовательских настроек.
Палитра виджета состоит из трех цветовых групп: активной, неактивной и нерабочей. Цветовая группа выбирается в зависимости от текущего состояния виджета:
• группа Active используется для виджетов текущего активного окна;
• группа Inactive используется виджетами других окон;
• группа Disabled используется отключенными виджетами любого окна.
Функция QWidget::palette возвращает палитру виджета в виде объекта QPalette. Цветовые группы определяются как элементы перечисления типа QPalette::QColorGroup. Удобная функция QWidget::colorGroup возвращает правильную цветовую группу текущего состояния виджета, и поэтому нам редко придется выбирать цвет непосредственно из палитры.
Когда нам нужно получить соответствующую кисть или цвет для рисования, правильный подход связан с применением текущей палитры, полученной функцией QWidget::palette, и соответствующей ролевой функции, например QPalette::foreground. Каждая ролевая функция возвращает кисть, что обычно и требуется, однако если нам нужен только цвет, его можно извлечь из кисти, как мы это делали в paintEvent. По умолчанию возвращаемые кисти соответствуют состоянию виджета, поэтому нам не надо указывать цветовую группу.
Функция paintEvent завершает рисование изображения. Вызов IconEditor::pixelRect возвращает QRect, который определяет область перерисовки. Мы не выдаем пиксели, которые попадают за пределы данной области, обеспечивая простую оптимизацию.
Рис. 5.4. Вычерчивание прямоугольника при помощи QPainter.
Мы вызываем QPainter::fillRect для вывода на экран масштабируемого пикселя. QPainter::fillRect принимает QRect и QBrush. Передавая QColor в качестве кисти, мы обеспечиваем равномерное заполнение области.
64 QRect IconEditor::pixelRect(int i, int j) const
65 {
66 if (zoom >= 3) {
67 return QRect(zoom * i + 1, zoom * j + 1, zoom - 1, zoom - 1);
68 } else {
69 return QRect(zoom * i, zoom * j, zoom, zoom);
70 }
71 }
Функция pixelRect возвращает объект QRect, который может использоваться функцией QPainter::fillRect. Параметры i и j являются координатами пикселя в QImage, а не в виджете. Если коэффициент масштабирования равен 1, обе системы координат будут полностью совпадать.
Конструктор QRect имеет синтаксис QRect(x, у, width, height), где (x, у) являются координатами верхнего левого угла прямоугольника, a width и height являются размерами прямоугольника (шириной и высотой). Если коэффициент масштабирования равен не менее 3, мы уменьшаем размеры прямоугольника на один пиксель по горизонтали и по вертикали, чтобы не загораживать линии сетки.
72 void IconEditor::mousePressEvent(QMouseEvent *event)
73 {
74 if (event->button == Qt::LeftButton) {
75 setImagePixel(event->pos, true);
76 } else if (event->button == Qt::RightButton) {
77 setImagePixel(event->pos, false);
78 }
79 }
Когда пользователь нажимает кнопку мышки, система генерирует событие «клавиша мышки нажата» (mouse press). Путем переопределения функции QWidget::mousePressEvent мы можем обработать это событие и установить или стереть пиксель изображения, находящийся под курсором мышки.
Если пользователь нажал левую кнопку мышки, мы вызываем закрытую функцию setImagePixel c true в качестве второго аргумента, указывая на необходимость установки цвета пикселя на текущий цвет пера. Если пользователь нажал правую кнопку мышки, мы также вызываем функцию setImagePixel, но передаем false для стирания пикселя.