| Home · All Classes · Main Classes · Grouped Classes · Modules · Functions |
[Предыдущая: Структура Interview] [Начало] [Далее: Классы Работы с Текстом Scribe]
Данный документ описывает систему рисования Qt 4 и приводит сравнение между подходами к рисованию используемыми в Qt 3 и Qt 4.
Система рисования Qt 4 основана прежде всего на классах QPainter, QPaintDevice и QPaintEngine. QPainter это класс выполняющий операции рисования такие как drawLine() и drawRect(). QPaintDevice реализует устройство, на котором можно создавать изображение используя QPainter;QWidget и QPixmap как QPaintDevices. QPaintEngine представляет интерфейс, который используется, чтобы рисовать на устройства различного типа.
В Qt 3 QPainter использовался для рисования на виджетах и растровых рисунках. (Так же с его помощью можно было выводить изображение на принтер в Windows и Mac OS X.) Когда необходимо было создать другие устройства рисования, такие как QPrinter на X11, их произвели от QPaintDevice и переопределили виртуальную функцию QPaintDevice::cmd(). Вторичное устройство рисования использовалось как внешенее устройство.
QPainter был способен работать с внешними устройствами и был способен преобразовать любую операцию рисования в последовательность вызовов функции each paint operation to the reimplemented cmd() function. Это позволяло работать с произвольными устройствами, но данный подход имеет некоторые неудобства которые мы сгладили в Qt 4. Одно из неудобств заключалось в том, что устройство не могло быть повторно использовано: возможности рисования на виджетах (растровых изображениях) QPainter были привязаны к платформе к которой был привязан QPainter. Поэтому поддержка устройства многократного использования типа OpenGL была не удобна и не очень эффективна.
Это подтолкнуло нас к разработке нового и эффективного API для Qt 4.
В Qt 4 мы ввели абстрактный класс QPaintEngine. Реализация данного класса предоставляет функциональные возможности для рисования на устройствах определенных типов. Внутри класс QPaintEngine использует QPainter и QPaintDevice. Это скрыто от прикладных программистов если они не создают собственный классы устройств на основе подклассов QPaintEngine. В настоящее время Qt реализует движки рисования для следующих платформ и API:
Чтобы реализовать поддержку новой основы для рисования, Вы должны произвести свой класс от QPaintEngine и заново реализовать виртуальные функции. Ваш класс также должен происходить от QPaintDevice и реализовать виртуальную функцию QPaintDevice::paintEngine() чтобы указать QPainter движку рисования как необходимо рисовать на данном специфическом устройстве.
Главное достоинство данного подхода в том, что все рисование выполняется единообразно. Это означает что поддержка индивидуальных особенностей и сохранение стандарных функций стали намного проще.
В Qt 4 стало возможным заполнить формы с помощью градиентных кистей. Градиент в данном контексте обозначает плавный переход от данного цвета в первой точке к другому цвету во второй точке. Градиент может быть задан как переход от одного цвета к другому или как переход через несколько цветов позиции которых заданы в пределах области градиента. Qt 4 поддерживает линейный, радиальный и конический градиенты.
Линейный градиент задают с использованием двух контрольных точек. Установку линейной градиентной заливки выполняют создавая объект QLinearGradient и задавая его в качестве кисти.
QLinearGradient gradient(0, 0, 100, 100);
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(0.5, Qt::green);
gradient.setColorAt(1, Qt::blue);
painter.setBrush(gradient);
painter.drawRect(0, 0, 100, 100);
Данный код приведет к отображению следующего растрового рисунка:

Радиальный градиент задают указывая центр, радиус и фокус. Установку радиальной градиентной заливки выполняют создавая объект QRadialGradient и задавая его в качестве кисти.
QRadialGradient gradient(50, 50, 50, 30, 30);
gradient.setColorAt(0.2, Qt::white);
gradient.setColorAt(0.8, Qt::green);
gradient.setColorAt(1, Qt::black);
painter.setBrush(gradient);
painter.drawEllipse(0, 0, 100, 100);
Данный код приведет к отображению следующего растрового рисунка:

Конический градиент задают указывая центр и угол начала. Установку конической градиентной заливки выполняют создавая объект QConicalGradient и задавая его в качестве кисти.
QConicalGradient gradient(60, 40, 0);
gradient.setColorAt(0, Qt::black);
gradient.setColorAt(0.4, Qt::green);
gradient.setColorAt(0.6, Qt::white);
gradient.setColorAt(1, Qt::black);
painter.setBrush(gradient);
painter.drawEllipse(0, 0, 100, 100);
Данный код приведет к отображению следующего растрового рисунка:

Qt 4 поддерживает альфасмешивание контруров и заполнения фигур. Цветовой альфаканал задается в QColor. Альфа-канал определяет эффект прозрачности, 0 обозначает полностью прозрачный цвет, а 255 обозначает полностью непрозрачный цвет. Например:
// Задание полупрозрачного красного
painter.setBrush(QColor(255, 0, 0, 127));
painter.drawRect(0, 0, width()/2, height());
// Задание полупрозрачного синего
painter.setBrush(QColor(0, 0, 255, 127));
painter.drawRect(0, 0, width(), height()/2);
Данный код приведет к выводу следующего изображения:

Рисование с использованием альфасмешивания поддерживается в системах Windows, Mac OS X и в X11 с установленным расширением X Render.
Теперь возможно работать с QPainter на QGLWidget так, будто это обычный QWidget. Это позволяет нам использовать высокоуровневый OpenGL операций рисования таких как преобразования и рисование на растровой карте.
На платформах, на которых это поддерживается API рисования, мы предоставляем возможность сглаживания контуров изображений примитивов.
// Одна линия без сглаживания линий
painter.drawLine(0, 0, width()/2, height());
// Одна линия со сглаживанием линий
painter.setRenderHint(QPainter::Antialiasing);
painter.drawLine(width()/2, 0, width()/2, height());
Данная программа выводит рисунок:

Сглаживание поддерживается при рисовании на QImage во всех системах, кроме X11 без установленного X Render.
В системе рисования Qt 4 используется большое количество встроенных операций с графикой. В результате многие действия могут быть выполнены на аппаратных средствах ЭВМ, что дает большую скорость выполнения программы.
Среди таких операций родные преобразования (Mac OS X и OpenGL), выполняющие рисование на матрице намного быстрее. Некоторые действия отрисовки растровых изображений также приближены к выполнения с помощью аппаратных средств.
Контур рисования - это объект построенный из некоторого количества элементарных блоков, таких как праямоугольники, эллипсы, линии и кривые. Контур может быть использован для заполнения, выделения и обрезки. Главное преимущество контуров перед обычным рисование растровых рисунков в том, что можно создать нелинейные формы, которые в любой момент могут быть изменены.
Контуры могут вглючать в себя как открытые подконтуры, такие как прямоугольники или эллипсы так и открытые (в этом случае подконтуры не могут быть заполнены).
Ниже приведен пример использования контура. Объект рисования имеет светлоголубую кисть шириной в три пикселя. Сперва мы добаляем прямоугольник который становится закрытым подконтуром. Затем мы добавляем две кривые Безье и, наконец, рисуем весь контур.
QPainterPath path;
path.addRect(20, 20, 60, 60);
path.addBezier(0, 0, 99, 0, 50, 50, 99, 99);
path.addBezier(99, 99, 0, 99, 50, 50, 0, 0);
painter.drawPath(path);
Данный код приводит к отображению следующей картинки:

В Qt 4 все виджеты по умолчанию используют двойную буферизацию.
В предыдущих версиях Qt двойная буферизация была реализована с помощью заэкранной отрисовки изображения и последующего копирования его на экран. Например:
QPixmap buffer(size());
QPainter painter(&buffer);
// Код рисования
painter.end();
bitBlt(this, 0, 0, &buffer);
Теперь двойная буферизация поддерживается самим QWidget:
QPainter painter(this);
// Код рисования
painter.end();
Двойная буферизация включена по умолчанию, но может быть отключена с помощью задания в настройках виджета Qt::WA_PaintOnScreen.
unbufferedWidget->setAttribute(Qt::WA_PaintOnScreen);
В Qt 3 на перо и кисти не оказывала влияния матрица преобразований. Например, если Вы рисовали прямоугольник пером шириной в 1 используя вычисляемый контейнер изображения, в результате Вы все-равно получили бы прямоугольник с контуром шириной в 1. Это делает затруднительным реализацию операций типа масштабирования и печати с высоким разрешением.
В 4 перья и ручки исползуют матрицу преобразований.
Следует обратить внимание, что эта особенность еще в разработке и поддерживается не всеми платформами.
В Qt 4 возможно определить как контур должен быть заполнен. Это можно сделать жестко задав цвет или с помощью QBrush который позволяет задать структуру и градиент заполнения для текста и контура.
QLinearGradient gradient(0, 0, 100, 100);
gradient.setColorAt(0, Qt::blue);
gradient.setColorAt(1, Qt::red);
painter.setPen(QPen(gradient, 0));
for (int y=fontSize; y<100; y+=fontSize)
drawText(0, y, text);
Код приведенный выше выведет на экран следующий рисунок:

Большим шагом вперед по сравнению с предыдущими версиями в Qt 4 является создание движка растрового рисования позволяющего работать с QImage. Растровый движок QImage поддерживает все возможности QPainter (контуры, сглаживание, альфасмешивание и т.д.) и может использоваться на всех платформах.
Большое преимущество заключается в том, что можно гарантировать точность воспроизведения рисунка на любой платформе.
Рисование изображения также просто, как рисование на любом другом устройстве.
QImage image(100, 100, 32);
QPainter painter(&image);
// команды рисования.
painter.end();
Scalable Vector Graphics (SVG) - это язык описание статической и анимированной двухмерной векторной графики. Qt включает поддержку подпрофилей SVG 1.1 и SVG 1.2, и пользуется улучшенной системой рисования Qt 4. SVG-рисунки могут быть отображены на любом подклассе QPaintDevice, таком как QWidget, QImage и QGLWidget, используя преимущества каждого из них. Такой подход дает разработчикам гибкость и возможность экспериментировать и искать лучшее решение для конкретной ситуации.

Поскольку SVG - это основанный на XML формат, для чтения SVG-файлов требуется модуль QtXml. По этой причине классы для работы с SVG располагаются в отдельном модуле QtSvg.
Отображение в приложении рисунков SVG так-же просто, как и отображение растровых изображений. Виджет QSvgWidget может быть размещен в любом месте пользовательского интерфейса, и при необходимости в него может быть загружено новое содержимое. Например, для загрузки и отображения заранее известного файла требуются минимальные усилия:
QSvgWidget window(":/files/spheres.svg");
window.show();
Для специфичных приложений класс QSvgRenderer предоставляет множество средств управления отображением и анимацией SVG-графики.
[Предыдущая: Структура Interview] [Начало] [Следующая: Классы Работы с Текстом Scribe]
| Copyright © 2005 Trolltech | Trademarks | Qt 4.1.0 |