Цель лекции: Научиться создавать основным приёмам работы с графическими примитивами в Juce
Традиционно в программировании канвой называют область компонента, на которой можно рисовать графические примитивы, текст, а также отображать готовые изображения. Каждая точка канвы имеет координаты x и y. Начало системы координат (точка с координатами 0, 0) находится в верхне-левом углу канвы. Координата x возрастает при перемещении слева направо, а координата y — при перемещении сверху вниз. Координаты измеряются в пикселях, наименьших элементах поверхности изображения, с которыми можно манипулировать. Важнейшее свойство пикселя — его цвет.
В отличие от других библиотек для создания графического интерфейса пользователя, Juce, как уже упоминалось ранее, позволяет рисовать не только на клиентской области окна компонента, но и на его заголовке, т.е. канвой является вся поверхность компонента.
За перерисовку компонента отвечает виртуальная функция virtual void Component::paint(Graphics g), с которой мы уже знакомы по примерам из предыдущих лекций. В классах, наследуемых от Component, эта функция должна быть переопределена для того, чтобы отобразить их содержимое.
До сих пор мы использовали этот метод лишь для того, чтобы производить заливку цветом фона компонента с помощью функции void Graphics::fillAll() const, которая, как мы видим, является методом класса Graphics.
Класс Graphics представляет собой платформ-независимый контекст рисования для прорисовки компонента или изображения. В каждом компоненте Juce есть хотя бы один объект этого класса, который передаётся в функцию virtual void Component::paint(Graphics g) в качестве параметра. Понятно, что класс обладает большим набором методов для рисования фоновых изображений компонентов, не ограничивающихся фоновой заливкой цветом. Он содержит методы для рисования линий, прямоугольников, окружностей и др. Рассмотрим их на простых примерах.
Для отображения точек используется метод класса Graphics void Graphics::setPixel(int x, int y) const, который закрашивает пиксель с координатами x и y текущим цветом. В листинге 7.1 приведён пример отображения восьми точек, расположенных по кругу (далее в этой главе для краткости в листингах будет приводиться лишь реализация метода paint).
#include "TCentralComponent.h"
//------------------------------------------------------
#include <cmath> // Функции вычисления синуса и косинуса
//------------------------------------------------------
TCentralComponent::TCentralComponent() : Component ("Central Component")
{
setSize(100, 100);
}
//------------------------------------------------------
TCentralComponent::~TCentralComponent()
{
}
//------------------------------------------------------
void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет рисуемых точек - чёрный
Canvas.setColour(Colours::black);
int iPointsNumber = 8; // Число точек
// Вычисляем координаты точек
for(int i = 0; i < iPointsNumber; ++i)
{
float fAngle = 2 * float_Pi * i / iPointsNumber;
int iX = 50 + cos(fAngle) * 40;
int iY = 50 + sin(fAngle) * 40;
// Рисуем точку
Canvas.setPixel(iX, iY);
}
}
//------------------------------------------------------
void TCentralComponent::resized()
{
}
//------------------------------------------------------
Внешний вид работающей программы показан на рисунке 7.1 .
(рис 7.1) Программа, рисующая восемь точек на канве компонента содержимого
Обратите внимание, что для расчёта координат точек мы использовали константу float_Pi из заголовочного файла juce_MathsFunctions.h. В этом же файле объявлена константа double_Pi, отличающаяся от первой, как понятно из названия, точностью числа $$\pi$$.
Для рисования линий, из одной точки в другую, в классе Graphics реализованы методы void Graphics::drawLine(float startX, float startY, float endX, float endY) const и void Graphics::drawLine(float startX, float startY, float endX, float endY, float lineThickness) const. Отличие между методами в том, что первый рисует текущим цветом линию между точками с координатами startX, startY и endX, endY толщиной в 1 пиксель, а во втором толщину линии можно задать параметром lineThickness. Кроме того, в классе Graphics имеются функции с тем же названием, в которые в качестве параметра можно передавать объекты класса Line, включающие информацию о собственно линии и ряд методов для решения геометрических задач.
С помощью последовательного вызова методов , рис 7.2).
void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет рисуемых линий - чёрный
Canvas.setColour(Colours::black);
int iPointsNumber = 8;
// Массивы для хранения координат точек,
// через которые будут проходить линии
Array<float> fXs;
Array<float> fYs;
// Вычисляем координаты точек
for(int i = 0; i < iPointsNumber; ++i)
{
float fAngle = 2 * float_Pi * i / iPointsNumber;
int iX = 50 + cos(fAngle) * 40;
int iY = 50 + sin(fAngle) * 40;
// и сохраняем их в массивах
fXs.add((float)iX);
fYs.add((float)iY);
}
for(int i = 0; i < iPointsNumber; ++i)
{
if(i != 7)
{
// Рисуем линию толщиной 3 пикселя
Canvas.drawLine(fXs[i], fYs[i], fXs[i + 1], fYs[i + 1], 3.0f);
}
else
{
// Завершаем многоугольник
Canvas.drawLine(fXs[7], fYs[7], fXs[0], fYs[0], 3.0f);
}
}
}
(рис 7.2) Программа, рисующая многоугольник на канве компонента содержимого
Кроме того, класс Graphics включает метод void Graphics::drawDashedLine(float startX, float startY, float endX, float endY, const float* dashLengths, int numDashLengths, float lineThickness = 1.0f) const, который рисует пунктирную линию по заданным характеристикам. Параметр dashLengths — массив чисел с плавающей точкой, которые содержат информацию о длинах рисуемых отрезках линии и разделяющих пробелов. Например, если в качестве параметра в функцию drawDashedLine будет передан массив {4, 5, 6, 7}, то будет нарисована линия с отрезком в 4 пикселя, пробелом в 5 пикселей, отрезком в 6 пикселей и пробелом в 7 пикселей. Пример использования метода приведён в листинге 7.3; внешний вид работающей программы показан на рисунке 7.3 .
void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет рисуемых линий - чёрный
Canvas.setColour(Colours::black);
int iPointsNumber = 8;
// Массивы для хранения координат точек,
// через которые будут проходить линии
Array<float> fXs;
Array<float> fYs;
// Вычисляем координаты точек
for(int i = 0; i < iPointsNumber; ++i)
{
float fAngle = 2 * float_Pi * i / iPointsNumber;
int iX = 50 + cos(fAngle) * 40;
int iY = 50 + sin(fAngle) * 40;
// и сохраняем их в массивах
fXs.add((float)iX);
fYs.add((float)iY);
}
// Отрезок линии - 8 пикселей,
// пробел - 4 пикселя
float fDashLengths[] = {8, 4};
for(int i = 0; i < iPointsNumber; ++i)
{
if(i != 7)
{
// Рисуем линию толщиной 3 пикселя
Canvas.drawDashedLine(fXs[i], fYs[i], fXs[i + 1], fYs[i + 1],
fDashLengths, 2, 3.0f);
}
else
{
// Завершаем многоугольник
Canvas.drawDashedLine(fXs[7], fYs[7], fXs[0], fYs[0],
fDashLengths, 2, 3.0f);
}
}
}
(рис 7.3) Программа, рисующая пунктиром многоугольник на канве компонента содержимого
Прямоугольник — одна из самых распространённых геометрических фигур. Для рисования прямоугольников класс Graphics включает специальные методы: void Graphics::drawRect(int x, int y, int width, int height, int lineThickness = 1) const и void Graphics::drawRect(int x, int y, int width, int height, float lineThickness = 1.0f) const. Как можно видеть, разница между методами лишь в последнем параметре: в первой функции толщина линии контура прямоугольника задаётся целым числом, а во второй — числом с плавающей точкой. Понятно, что x и y — это координаты верхне-левого угла прямоугольника, width — его ширина, а height — высота.
Вышеприведённые функции рисуют лишь контур прямоугольника. Для заливки его текущим (заданным) цветом используются методы void Graphics::fillRect(int x, int y, int width, int height) const и void Graphics::fillRect(float x, float y, float width, float height) const. Значения параметров этих методов те же, что и у вышеприведённых функций.
Кроме того, класс Graphics включает одноимённые методы, которые принимают в качестве параметра объект класса Rectangle, хранящий информацию о многоугольнике.
Рассмотрим рисование прямоугольников на простом примере. Задайте размеры компонента содержимого программы равными 120 на 120 пикселей. Нарисуем на его канве два квадрата — красный и, внутри первого, второй, жёлтый. Обведём второй прямоугольник чёрным контуром (, рис 7.4" type="example"/>, void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет заливки первого прямоугольника - красный
Canvas.setColour(Colours::red);
// Рисуем первый прямоугольник
Canvas.fillRect(10, 10, 100, 100);
// Цвет заливки второго прямоугольника - жёлтый
Canvas.setColour(Colours::yellow);
// Рисуем второй прямоугольник (внутри первого)
Canvas.fillRect(20, 20, 80, 80);
// Цвет контура второго прямоугольника - чёрный
Canvas.setColour(Colours::black);
// Обводим второй прямоугольник контуром
// толщиной 3 пикселя
Canvas.drawRect(20, 20, 80, 80, 3);
}
Также класс Перепишем пример из листинга 7.4 с использованием функций , рис 7.4" type="example">листинга 7.4 с использованием функций , void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет заливки первого прямоугольника - красный
Canvas.setColour(Colours::red);
// Рисуем первый прямоугольник
Canvas.fillRoundedRectangle(10, 10, 100, 100, 10);
// Цвет заливки второго прямоугольника - жёлтый
Canvas.setColour(Colours::yellow);
// Рисуем второй прямоугольник (внутри первого)
Canvas.fillRoundedRectangle(20, 20, 80, 80, 10);
// Цвет контура второго прямоугольника - чёрный
Canvas.setColour(Colours::black);
// Обводим второй прямоугольник контуром
// толщиной 3 пикселя
Canvas.drawRoundedRectangle(20, 20, 80, 80, 10, 3);
}
Метод , рис 7.6). Набор рассмотренных графических примитивов Juce даёт широкие возможности для рисования на канве компонентов, однако если их недостаточно, то есть возможность построения произвольных фигур как со сплошной заливкой, так и заливкой линейным и Рассмотрим использование класса на примере рисования сектора, залитого Градиент задаётся объектом класса Задание заливки градиентом обеспечивает метод класса Для отображения собственно фигуры (объект класса ). Объявим переменную Для того, чтобы облегчить расчёт координат фигуры, можно воспользоваться программой the jucer из комплекта поставки библиотеки (см. лекцию 5 ). Отрисовку фигуры осуществляет функция ). Внешний вид работающей программы представлен на рисунке 7.7 . Здесь перечислены далеко не все возможности класса В следующей лекции будут рассмотрены специализированные компоненты библиотеки Juce для отображения и ввода текстовой информации. Но помимо этих компонентов отображать текст можно на поверхности любого компонента в виде графики, переопределяя его метод Так же, как и при рисовании графических примитивов, цвет текста задаётся методом Вывод текста на канву осуществляют два метода: Надписи в обоих методах делаются в соответствии с текущими установками шрифта компонента. Для задания шрифта текста используются методы класса Пример вывода текста на канву компонента содержимого этими методами представлен в листинге 7.8. Внешний вид работающей программы представлен на рисунке 7.8 . По сравнению с версией 1.53 метод Один из конструкторов класса Понятно, что пример из листинга 7.3 легко переделать для версии ) Для рисования чего бы то ни было на канве компонентов в Juce используется метод Создайте программу с одним главным окном белого цвета с неизменяемыми размерами. С помощью методов класса Архив с исходными текстами примеров Вы можете скачать здесь
(рис 7.4) Программа, рисующая два квадрата на канве компонента содержимого
Graphics включает методы для рисования / заливки прямоугольников с закруглёнными углами. Это void Graphics::drawRoundedRectangle(float x, float y, float width, float height, float cornerSize, float lineThickness) const и void Graphics::fillRoundedRectangle(float x, float y, float width, float height, float cornerSize) const, соответственно. Параметр cornerSize задаёт, насколько сильно должны быть закруглены углы прямоугольника. При присвоении параметру нулевого значения углы не будут закруглены. При присвоении ему значения 100 прямоугольник превратится в эллипс. Также имеются Rectangle.
(рис 7.5) Программа, рисующая два квадрата с закруглёнными углами на канве компонента содержимого
Рисование эллипсов
void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет заливки эллипса - светло-зелёный
Canvas.setColour(Colours::lightgreen);
// Рисуем эллипс
Canvas.fillEllipse(10, 10, 100, 50);
// Цвет контура эллипса - синий
Canvas.setColour(Colours::blue);
// Обводим эллипс контуром
// толщиной 3 пикселя
Canvas.drawEllipse(10, 10, 100, 50, 3);
}
(рис 7.6) Программа, рисующая эллипс на канве компонента содержимого
Рисование произвольных фигур
Path, который позволяет отрисовывать прямые и кривые линии, образующие фигуры как замкнутым, так и разомкнутым контуром.ColourGradient, конструктор которого принимает следующие параметры: ColourGradient::ColourGradient(const Colour colour1, float x1, float y1, const Colour colour2, float x2, float y2, bool isRadial), где x1 и y1 — координаты первого цвета градиента (colour1), а x2 и y2 — второго (colour2). Флаг isRadial показывает, является ли градиент радиальным (в нашем случае параметр принимает значение false).Graphics void Graphics::setGradientFill(const ColourGradient gradient), принимающий объект класса ColourGradient в качестве параметра.Path в качестве закрытого члена класса компонента содержимого нашей программы (TCentralComponent). После этого последовательно вызываем следующие функции:
void Path::clear() throw() - удаляет все линии из объекта класса Path;void Path::startNewSubPath(float startX, float startY) — начинает новую линию, исходя из параметров, начальной позиции;void Path::quadraticTo(float controlPointX, float controlPointY, float endPointX, float endPointY) — рисует квадратную кривую Безье по заданным координатам;void Path::lineTo(float endX, float endY) — замыкает кривую между её последней точкой и точкой с координатами endX, endY;void Path::closeSubPath() - завершает рисование замкнутой фигуры. Например, если мы рисуем треугольник, следует дважды вызвать метод lineTo, а затем — closeSubPath.#include "TCentralComponent.h"
//------------------------------------------------------
TCentralComponent::TCentralComponent() : Component ("Central Component")
{
setSize(200, 200);
}
//------------------------------------------------------
TCentralComponent::~TCentralComponent()
{
}
//------------------------------------------------------
void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Заливка линейным градиентом от светло-голубого до зелёного цвета
ColourGradient LinearGradient(Colour(0xff00f7ff), 72.0f, 216.0f,
Colours::green, 296.0f, 56.0f,
false);
Canvas.setGradientFill(LinearGradient);
// Заливаем градиентом сектор -
// объект класса Path
Canvas.fillPath(Sector); // Path Sector - объявлен в качестве закрытого
// члена класса TCentralComponent
}
//-------------------------------------------------------
void TCentralComponent::resized()
{
// Отрисовка фигуры
Sector.clear();
Sector.startNewSubPath(84.0f, 28.0f);
Sector.quadraticTo(172.0f, 60.0f, 140.0f, 156.0f);
Sector.lineTo(28.0f, 116.0f);
Sector.closeSubPath();
}
//------------------------------------------------------
(рис 7.7) Программа, рисующая сектор с градиентной заливкой на канве компонента содержимого
Path, однако они достаточно хорошо описаны в документации к библиотеке.Вывод текста на канву компонента
paint.void Graphics::setColour(const Colour newColour).
void Graphics::drawSingleLineText(const String text, int startX, int baselineY) const — выводит текст text, расположенный в одну строку, начиная с позиции с координатами startX, baselineY;void Graphics::drawMultiLineText(const String text, int startX, int baselineY, int maximumLineWidth) const — выводит текст text, расположенный в несколько строк, начиная с позиции с координатами startX, baselineY. Параметр maximumLineWidth задаёт максимальную ширину строки в пикселях; часть текста, ширина которой превышает эту величину, переносится на следующую строку.Graphics:
void Graphics::setFont(const Font newFont) — принимает в качестве параметра новый объект класса шрифта Font;void Graphics::setFont(float newFontHeight, int fontStyleFlags = Font::plain) — задаёт новые размер и стиль текущего шрифта; гарнитура при этом остаётся неизменной.void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет выводимого текста - чёрный
Canvas.setColour(Colours::black);
Canvas.drawSingleLineText(tr("Однострочный текст выведен
на позицию (10, 30)"), 10, 30);
// Цвет выводимого текста - синий
Canvas.setColour(Colours::blue);
Canvas.setFont(Font(25.0000f, Font::bold));
Canvas.drawMultiLineText(tr("Многострочный текст выведен
на позицию (10, 80).
\n\n\t\t\t\t\t\t\t\t\tПРИВЕТ, МИР!"),
10, 80, 550);
}
(рис 7.8) Программа, рисующая однострочный и многострочный текст на канве компонента содержимого
Особенности Juce 2.0
Graphics::drawDashedLine во второй версии Juce претерпел изменения: теперь в качестве параметров принимаются не числа — координаты начала и конца пунктирной линии, а объект класса Line, предназначенного как раз-таки для хранения информации о линиях:void Graphics::drawDashedLine(
const Line< float > line,
const float* dashLengths,
int numDashLengths,
float lineThickness = 1.0f, int
dashIndexToStartFrom = 0) const
Line принимает в качестве параметров значения координат начала и конца линии: Line<ValueType>::Line(ValueType startX, ValueType startY, ValueType endX, ValueType endY).void TCentralComponent::paint(Graphics Canvas)
{
// Фон виджета - белый
Canvas.fillAll(Colours::white);
// Цвет рисуемых линий - чёрный
Canvas.setColour(Colours::black);
int iPointsNumber = 8;
// Массивы для хранения координат точек,
// через которые будут проходить линии
Array<float> fXs;
Array<float> fYs;
// Вычисляем координаты точек
for(int i = 0; i < iPointsNumber; ++i)
{
float fAngle = 2 * float_Pi * i / iPointsNumber;
int iX = 50 + cos(fAngle) * 40;
int iY = 50 + sin(fAngle) * 40;
// и сохраняем их в массивах
fXs.add((float)iX);
fYs.add((float)iY);
}
// Отрезок линии - 8 пикселей,
// пробел - 4 пикселя
float fDashLengths[] = {8, 4};
for(int i = 0; i < iPointsNumber; ++i)
{
if(i != 7)
{
// Рисуем линию толщиной 3 пикселя
Canvas.drawDashedLine(
Line<float>(fXs[i], fYs[i], fXs[i + 1], fYs[i + 1]),
fDashLengths, 2, 3.0f);
}
else
{
// Завершаем многоугольник
Canvas.drawDashedLine(
Line<float>(fXs[7], fYs[7], fXs[0], fYs[0]),
fDashLengths, 2, 3.0f);
}
}
}
Краткие итоги
paint класса Graphics, который включает ряд методов для изображения графических примитивов и произвольных фигур.Упражнение
Graphics нарисуйте на канве компонента содержимого российский флаг.Дополнительные материалы
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.