Оглавление
Система рисования ArthurДанный документ описывает систему рисования Qt 4 и приводит сравнение между подходами к рисованию, используемыми в Qt 3 и Qt 4. АрхитектураСистема рисования Qt 4 основана, в основном, на классах QPainter, QPaintDevice и QPaintEngine. QPainter - это класс, выполняющий операции рисования, такие как drawLine() и drawRect(). QPaintDevice реализует устройство, на котором можно создавать изображение, используя QPainter; QWidget и QPixmap являются QPaintDevices. QPaintEngineпредоставляет интерфейс, который используется, чтобы рисовать на устройствах различного типа. Оглянемся на Qt 3В Qt 3 QPainter использовался для рисования на виджетах и растровых рисунках. (Так же с его помощью можно было выводить изображение на принтер в Windows и Mac OS X.) Когда потребовалась поддержка других устройств рисования, таких как QPrinter на X11, это сделали унаследовав от QPaintDevice и переопределив виртуальную функцию QPaintDevice::cmd(). Переопределённое устройство рисования, рассматривавшееся как внешнее устройство. QPainter был способен работать с внешними устройствами и был способен преобразовать любую операцию рисования в последовательность вызовов переопределнной функции cmd(). Это позволяло работать с произвольными устройствами, но данный подход имеет некоторые неудобства, которые мы сгладили в Qt 4. Одно из неудобств заключалось в том, что устройство не могло быть повторно использовано: возможности рисования на виджетах (растровых изображениях) QPainter были привязаны к платформе, к которой был привязан QPainter. Поэтому поддержка устройства многократного использования типа OpenGL была неудобна и не очень эффективна. Это подтолкнуло нас к разработке нового и эффективного API для Qt 4. Реализация рисования в Qt 4В Qt 4 мы ввели абстрактный класс QPaintEngine. Реализация данного класса предоставляет функциональные возможности для рисования на устройствах определенных типов. Класс QPaintEngine используется внутри QPainter и QPaintDevice. Он скрыт от прикладных программистов, если они не переопределяют собственные типы устройств на основе подклассов QPaintEngine. В настоящее время Qt предоставляет механизмы рисования для следующих платформ и API:
Чтобы реализовать поддержку новой основы для рисования, вы должны произвести свой класс от QPaintEngine и переопределить виртуальные функции. Ваш класс также должен быть унаследован от QPaintDevice и переопределить виртуальную функцию QPaintDevice::paintEngine(), чтобы указать QPainter какой движок рисования необходимо использовать на данном конкретном устройстве. Главное достоинство данного подхода в том, что все рисование выполняется единообразно. Это означает, что поддержка индивидуальных особенностей и сохранение стандартных функций стали намного проще. Новые возможности системы рисования Qt 4Градиентные кистиВ 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); Данный код приведет к отображению следующего растрового рисунка: Альфа-смешивание (Alpha-Blended) изображенийВ Qt 4 реализовано альфа-смешивание (Alpha-Blended) контуров и внутренних областей. Цветовой альфа-канал задается в 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Теперь возможно работать с 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 используется большое количество встроенных операций с графикой. В результате многие действия могут быть выполнены на аппаратных средствах ЭВМ, что дает большую скорость выполнения программы. Среди таких операций родные преобразования (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. Это делает затруднительным реализацию операций типа масштабирования и печати с высоким разрешением. В Qt 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); Данный код приведет к отображению следующего растрового рисунка: QImage в качестве устройства рисованияБольшим шагом вперед по сравнению с предыдущими версиями в Qt 4 является создание движка растрового рисования, позволяющего работать с QImage. Растровый движок QImage поддерживает все возможности QPainter (контуры, сглаживание, альфа-смешивание и т.д.) и может использоваться на всех платформах. Большое преимущество заключается в том, что можно гарантировать точность воспроизведения рисунка на любой платформе. Рисование изображения также просто, как рисование на любом другом устройстве. QImage image(100, 100, 32); QPainter painter(&image); // команды рисовальщика. painter.end(); Поддержка рендеринга SVGScalable Vector Graphics (SVG) - это язык описание статической и анимированной двухмерной векторной графики. Qt включает поддержку статической функциональности SVG 1.2 Tiny, пользуясь улучшенной системой рисования Qt 4. SVG-рисунки могут быть отображены на любом подклассе QPaintDevice, таком как QWidget, QImage и QGLWidget, используя преимущества каждого из них. Такой подход дает разработчикам гибкость и возможность экспериментировать и находить наилучшее решение для конкретной ситуации. Поскольку SVG - это основанный на XML формат, для чтения SVG-файлов требуется модуль QtXml. По этой причине классы для работы с SVG располагаются в отдельном модуле QtSvg. Отображение в приложении рисунков SVG также просто, как и отображение растровых изображений. Виджет QSvgWidget может быть размещен в любом месте пользовательского интерфейса, и при необходимости в него может быть загружено новое содержимое. Например, для загрузки и отображения заранее известного файла требуются минимальные усилия: QSvgWidget window(":/files/spheres.svg"); window.show(); Для специфичных приложений класс QSvgRenderer предоставляет множество средств управления визуализации и анимации SVG-графики. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |