Текст книги "Платформа J2Me"
Автор книги: Автор Неизвестен
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 8 (всего у книги 21 страниц)
Игровые действия отражены на других клавишах, потому что большинство устройств не имеет клавиш или кнопок специально для игр. Значение игрового действия соответствует одному или более кодам клавиш, являющихся двоичными значениями, каждое из которых однозначно соответствует клавише. Вы можете определить определенное отображение с помощью следующих двух методов:
public int getKeyCode (int gameAction)
public int getGameAction(int keyCode)
В листинге 6.2 эти методы используются для вывода диагностической информации о каждом полученном событии отпускания клавиши. Если вы запустите эту программу и исследуете результат, вы увидите, что не каждая клавиша имеет связанное с ней игровое действие. В данном случае метод getGameAction () возвращает значение 0. Более того, не все устройства реализуют GAME_A, GAME_B, GAME_C и GAME_D. Примером устройства, которое не использует эти игровые действия, является Motorola Accompli 008.
Графическое рисование
Вы, несомненно, обратили внимание, что canvas, показанный на рисунке 6.2, был чистым за исключением экранной клавиши Exit (Выход). Причина этого кроется в том, что класс Canvasl не описывает свое визуальное представление. Все конкретные подклассы Canvas должны определять свой внешний вид для того, чтобы визуализировать какие-либо визуальные атрибуты. Для этого они должны привлекать помощь класса javax.microedition.lcdui.Graphics. Основная цель класса Graphics заключается в поддержке рисования на Canvas.
Графическая модель
Класс Graphics определяет возможности низкоуровневого графического рисования. Если вы уже разрабатывали программы на AWT или Swing, этот класс покажется вам очень знакомым. В действительности его свойства и программный интерфейс практически идентичны, хотя и являются подмножеством свойств класса Graphics J2SE.
Класс Graphics определяет модель, которая позволяет приложениям рисовать– или раскрашивать на языке Java – базовые двухмерные фигуры на Canvas. Описанным методом public void paint(Graphics g) осуществляется рисование в вашем подклассе Canvas, подменяя объявленный метод protected abstract в Canvas. Класс Canvas имеет пустое paint(Graphics g) определение, что объясняет, почему он не создает какого-либо визуального представления.
Каждый конкретный подкласс Canvas имеет доступ к объекту Graphics. Этот объект Graphics является копией графического контекста устройства и извлекает зависящий от реализации графический контекст устройства, являющийся частью программного обеспечения операционной системы устройства.
Объект Graphics, с которым вы работаете, создан реализацией Canvas при инициализации объекта Canvas. Это одна из главных причин, почему вы должны убедиться, что ваш конструктор подкласса Canvas вызывает super()! Реализация пересылает графический объект в ваш Canvas, когда он вызывает метод вашего класса paint (Graphics g).
Класс Graphics
Класс Graphics поддерживает следующие абстракции:
– рисование и заливка двухмерных геометрических фигур;
– выбор цветов для графической ручки;
– выбор шрифтов для рисования текста;
– отсечение областей для рисования (clipping);
– перенос координатной системы Graphics.
Устройства различаются в своей поддержке атрибутов, таких, как цвет. Поэтому класс Display предоставляет методы:
public int isColorO
public int numColors()
так что вы можете получить информацию о поддержке данным устройством цвета и количестве предоставляемых цветов или поддержке какого-либо числа уровней шкалы серого цвета для устройств, не поддерживающих цвет.
Первостепенной абстракцией, определяемой классом Graphics, является представление о Canvas, как о двухмерной сетке точек или пикселей. На рисунке 6.3 представлено схематичное изображение этой области для рисования. Графический контекст определяет эту координатную плоскость (х, у), в которой координаты лежат между пикселями, практически так же, как и курсор вашего любимого текстового редактора всегда лежит между двумя символами.
Рисунок 6.3. Класс Graphics представляет дисплей как двухмерную сетку пикселей
Базовое геометрическое рисование
Класс Graphics предоставляет операции по рисованию и заливке следующих типов геометрических фигур:
– линии;
– прямоугольники;
– дуги;
– текстовые символы.
Для всех операций по рисованию геометрических фигур класс Graphics использует графическую ручку, которая рисует линии шириной в один пиксель. Графическая ручка рисует слева направо и сверху вниз со своего координатного местоположения, как показано на рисунке 6.3. Взглянув на несколько примеров, вы лучше поймете принципы ее действия.
Линии. На рисунке 6.4 показаны линии, нарисованные в Canvas.
Рисунок 6.4. Вы можете рисовать линии в Canvas. Вы можете сделать линии толще одного пикселя, нарисовав прилегающие линии ручкой одного цвета
В листинге 6.3 показан исходный код, который создает рисунок 6.4, но я опустил код MID-лета, который отображает это. Вы можете найти полный исходный код по адресу http://www.phptr.com/. Для остальных примеров, приведенных в этой главе, предполагается, что отображаемые классы, которые вы видите здесь, созданы и отображаются MID-летом в стиле, сходном с примерами, которые вы видели в предыдущих главах. Исходя из этого, я покажу вам только новый код.
Листинг 6.3. Демонстрационная программа описывает метод paint (), который гарантирует, что некоторые визуальные представления появляются на дисплее устройства
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.raicroedition.lcdui.Command;
/*
Рисует серию линий для демонстрации различных типов и стилей линий, которые могут быть нарисованы с помощью класса Graphics.
@смотри javax.microedition.Icdui.Graphics
*/
public class LineDemo extends Canvas.
implements CommandListener
}
// Константа, которая представляет белый цвет.
private static final int WHITE = OxFF «16 | OxFF «8 I OxFF;
private Command back = new Command("Back", Command.BACK, 1);
private GraphicsDemo gDemo = GraphicsDemo.getlnstance(};
private Display display = Display.getDisplay(gDemo);
/**
Конструктор No-arg.
*/
public LineDemo()
{
super ();
addCommand(back);
setCommandListener(this);
display.setCurrent(this);
}
/* *
Рисует отсекаемый белый прямоугольник, эффективно стирающий все, что было изображено в Canvas перед этим.
"/
protected void paintdipRect (Graphics g)
}
int clipX = g.getClipX ();
int clipY = g.getClipY();
int clipH = g.getdipHeight ();
int clipW = g.getClipWidth();
int color = g.getColor ();
g. setColor(WHITE);
g. fillRect(clipX, clipY, clipW, clipH);
g. setColor (color);
}
/ **
Отображает внешний вид этого подкласса Canvas.
* /
public void paint (Graphics g)
{
paintdipRect (g);
int width = getWidth();
int height = getHeight ();
g. drawLine (20, 10, width – 20, height – 34);
g. drawLine(20, 11, width – 20, height – 33);
g. drawLine(20, 12, width – 20, height – 32);
g. drawLine(20, 13, width – 20, height – 31);
g. drawLine(20, 14, width – 20, height – 30);
g. setStrokeStyle(Graphics.DOTTED);
g. drawLine(20, 24, width – 20, height – 20);
g. drawLine(20, 25, width – 20, height – 19);
g. drawLine(20, 26, width – 20, height – 18);
g. setStrokeStyle (Graphics.SOLID);
g. drawLine(20, 36, width – 20, height – 8);
}
public void commandAction(Command c, Displayable d)
{
if (c == back)
{
GraphicsDemo.getlnstanceO.display();
}
}
}
Метод paint (Graphics g) является основным в этом примере. Поскольку Canvas описывает этот метод как абстрактный, подклассы должны предоставлять конкретное описание. На экране, созданном программой в листинге 6.2, ничего не появляется, поскольку ее метод paint (Graphics g) не описывает никаких операций по рисованию.
Ваша программа должна выполнять все свои операции по рисованию в методе paint (Graphics g) на объекте Graphics, переданном ей. Вы запускаете стандартные операции по рисованию, предназначенные для класса Graphics, в этом экземпляре, который передан вашему Canvas.
Чтобы нарисовать линию, вы должны указать координаты (х, у) начальной и конечной точек. Координаты (х, у) определяются относительно точки (0, 0), которая, во время создания графического контекста, представляет пиксель, лежащий в верхнем левом углу дисплея, как показано на рисунке 6.3. Координата х определяет горизонтальное расстояние направо от колонки 0 (левый край дисплея), а координата у определяет вертикальное расстояние от строки 0, которая является верхним краем дисплея.
Ширина линий составляет один пиксель. Чтобы нарисовать более толстую линию, вы должны рисовать прилегающие линии, как демонстрируется в листинге 6.3. Три линии, показанные на рисунке 6.4, созданные с помощью листинга 6.3, имеют ширину в пять, три и один пиксель соответственно.
Кроме того, средняя линия отображена штрихпунктиром. Вы можете установить стиль штриховки для любого рисунка с помощью метода setStrokeStyle (), как демонстрируется в программе. Конкретное отображение линий, которые используют стиль штрихования Graphics.DOTTED, зависит от реализации.
Прямоугольники. Вы можете рисовать два вида прямоугольников: обычный и закругленный. На рисунке 6.5 показаны несколько прилегающих прямоугольников.
Рисунок 6.5. Прямоугольники, как и все геометрические фигуры, могут быть изображены различными цветами с помощью указания цвета графической ручки. Средний прямоугольник красный, хотя он и кажется опенком серого на рисунке
В листинге 6.4 показан исходный код paint (Graphics g) для этого примера.
Листинг 6.4. Демонстрационная программа RectangleDemo демонстрирует графические вызовы рисования прямоугольников. Обратите внимание, что это вызов на заполнение прямоугольников
import javax.microedition.lcdui.Canvas;
import javax.microedition.Icdui.Command;
import javax.microedition.Icdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.Icdui.Displayable;
import javax.microedition.Icdui.Graphics;
import javax.microedition.Icdui.Command;
/**
Рисует прямоугольники на Canvas с помощью графических методов в классе javax.microedition.Icdui.Graphics.
@смотри javax.microedition.Icdui.Graphics
*/
public class RectangleDemo extends Canvas
implements CommandListener
{
// Константа, представляющая белый цвет.
private static final int WHITE = OxFF «16 | OxFF «8 I OxFF;
private Command back = new Command("Back", Command.BACK, 1);
private Display display =
Display.getDisplay(GraphicsDemo.get!nstance());
/**
Конструктор No-arg. Вызывает конструктор no-arg Canvas.
*/
public RectangleDemo()
}
super ();
addCommand(back); setCommandListener(this);
display.setCurrent (this);
}
/**
Рисует белый отсекаемый прямоугольник, эффективно стирающий все, что было отображено на Canvas перед этим.
*/
protected void paintClipRect(Graphics g)
{
int clipX = g.getClipX ();
int clipY = g.getClipY();
int clipH = g.getClipHeight();
int clipW = g.getClipWidth ();
int color = g.getColor();
g. setColor (WHITE);
g. fillRect(clipX, clipY, clipW, clipH);
g. setColor (color);
}
/**
Отображает внешний вид этого подкласса Canvas.
*/
public void paint(Graphics g)
{
paintClipRect(g);
int width = getWidthO; int height = getHeight();
int xO = 5;
int yO = 5;
int barW = 10;
int initHeight = height – 10;
int deltaH = 10;
g. drawRect(xO, yO, barW, initHeight);
g. fillRect(xO + barW, yO + deltaH, barW, initHeight – deltaH + 1);
g. drawRect(xO + barW " 2, yO + deltaH * 2,
barW, initHeight – deltaH * 2);
g. setColor (255, 00, 00); g.fillRect(xO + bar» * 3, yO + deltaH * 3,
barW, initHeight – deltaH * 3 + 1); g. setColor (0," 0, 0);
g. drawRect(xO + barW * 4, yO + deltaH * 4,
barW, initHeight – deltaH * 4);
g. fillRect(xO + barW * 5, yO + deltaH * 5,
barW, initHeight – deltaH * 5 + 1);
g. drawRect(xO + barW * 6, yO + deltaH * 6,
barW, initHeight – deltaH * 6); g.fillRect(xO + barW * 1, yO + deltaH * 1,
barW, initHeight – deltaH * 7 + 1);
}
public void commandAction(Command c, Displayable d)
{
if (c == back)
{
GraphicsDemo.getlnstanceO.display!);
}
}
}
Дуги. Класс Graphics также поддерживает рисование дуг. Чтобы нарисовать дугу, вы должны указать шесть параметров. Эти параметры включают четыре размера, которые определяют ограничивающий дугу прямоугольник, ее начальный угол и ее конечный угол. Ограничивающий прямоугольник определяется теми же четырьмя параметрами, которые требуются для прямоугольников.
Процедура рисования отслеживает дугу вдоль ее пути от начального угла к конечному углу в направлении против часовой стрелки. Угол в 0 градусов располагается вдоль положительной оси X координатной плоскости. На рисунке 6.6 показаны две дуги, нарисованные методом paint (Graphics g) в листинге 6.5.
Рисунок 6.6. Как и другие геометрические фигуры, дуги могут быть нарисованы в режиме контура или заполненными
Листинг 6.5. Дуги могут быть нарисованы в виде очертания или заполненными, как и прямоугольники
import javax.microedition.lcdui.*;
/**
Демонстрирует рисование дуг с помощью класса Graphics.
@смотри javax.microedition.lcdui.Graphics
*/
public class ArcDemo extends Canvas
implements ComraandListener
{
public void paint(Graphics g)
{
paintClipRect(g);
}
int width = getWidth();
int height = getHeight ();
g. drawArc(5, 5, 80, 40, 90, 300);
g. fillArc(5, 60, 80, 40, 0, 250);
}
.
}
Обратите внимание, что вторая дуга заполнена и что она была создана с помощью метода fillArc () вместо метода drawArc ().
Текст. Класс Graphics также поддерживает «рисование» текстовых символов в Canvas. Три метода, перечисленные в таблице 6.4, являются методами класса Canvas, поддерживающими размещение текста в Canvas.
Таблица 6.4. Методы класса Canvas, которые поддерживают изображение текста на Canvas
Название метода отображения текста в Canvas – Описание
public void drawString(String str, int x, int y, int anchor) – Рисует символы, которые формируют строковую переменную с указанной точкой привязки в позиции, определяемой координатами (х, у]
public void drawSubstring(String str, int offset, int len, int x, int y, int anchor) – Рисует символы, которые формируют переменную подстроки, определяемую начальной точкой и сдвигом, с указанной точкой привязки в позиции, определяемой координатами (х, у)
public void drawChar (Char char, int x, int y, int anchor) – Рисует символ с указанной точкой привязки в позиции, определяемой координатами (х, у)
Эти методы вычисляют воображаемый ограничивающий прямоугольник, который описывает границы области, занимаемой текстом, вокруг текста, который необходимо изобразить, как показано на рисунке 6.7. Размеры этого прямоугольника зависят от длины строки и шрифта, используемого для отображения.
Параметры (х, у) в только что показанных методах представляют расположение ограничивающего прямоугольника. Параметр привязки определяет точку привязки ограничивающего прямоугольника. Точка привязки определяет, которая из шести возможных точек по периметру текста ограничивающего прямоугольника должна быть размещена в позицию (х, у).
На рисунке 6.7 показаны шесть точек привязки для регулирования расположения прямоугольника, ограничивающего текстовую строку. Значение точки привязки на самом деле является выбором нагрузки на точку ограничивающего прямоугольника. Два атрибута составляют нагрузку точки привязки: горизонтальная и вертикальная политики нагрузки. В таблице 6.5 описаны представляющие их константы класса Graphics. Они описывают public static final int.
Рисунок 6.7. Текст «рисуется» в границах воображаемого ограничивающего прямоугольника, который вычисляется стандартными текстовыми процедурами
Некоторый отображаемый текст
Таблица 6.5. Графические константы для определения политики привязки-нагрузки
Константа привязки – Описание
static int LEFT – Размещает левый край у координаты х
static int HCENTER – Размещает горизонтальный центр у координаты х
static int RIGHT – Размещает правый край у координаты х
static int TOP – Размещает верх у координаты у
static int BASELINE – Размещает нижнюю строку текста у координаты у
static int BOTTOM – Размещает низ ограничивающего прямоугольника у координаты у
static int VCENTER – Только для изображений, размещает вертикальный центр изображения у координаты у
Класс Graphics описывает эти константы для текущих значений горизонтальной нагрузки, а также определяет значения для текущих значений вертикальной нагрузки.
На рисунке 6.8 показан некоторый текст, отображаемый на Canvas, а в листинге 6.6 показан метод paint (Graphics g) исходного кода, который его отображает.
Рисунок 6.8. Чтобы нарисовать текст, укажите местоположение его точки привязки. Рисуйте вертикальный текст, определяя местоположение и отображая каждый символ текста
Листинг 6.6. Чтобы создать текст, укажите точку привязки и нагрузку точки привязки. Вы также можете указать шрифт текста, который будет отображен
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.rnicroedition.lcdui.CornmandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
/**
Отображает некоторый текст, «нарисованный» в Canvas.
Демонстрирует использование процедур рисования текста в Graphics.
@смотри javax.microedition.lcdui.Graphics
*/
public class TextDemo extends Canvas
implements CommandListener
}
public void paint(Graphics g)
}
paintClipRect(g);
int width = getWidth (); int height = "getHeight ();
g. setFont(Font.getDefault Font());
g. drawStriny("Default", 5, 30, Graphics.LEFT I Graphics.BOTTOM);
g. setFont (Font.get Font (Font.FACE_SYSTEM, Font.STYLE_PLAIN,
Font.SIZE_LARGE)); g.drawstring("Large", 5, 53, Graphics.LEFT | Graphics.BOTTOM);
g. set Font(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_ITALIC,
Font.SIZE_MEDIUM));
g. drawString("Medium", 5, 71, Graphics.LEFT I Graphics.BOTTOM);
g. set Font(Font.get Font(Font.FACE_PROPORTIONAL, Font.STYLE_UNDERLINED,
Font.SIZE_SMALL));
g. drawString("Small", 5, 90, Graphics.LEFT I Graphics.BOTTOM);
g. setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD,
Font.SIZE_MEDIUM));
g. drawString ("V", width – 10, 20, Graphics.RIGHT I Graphics.BOTTOM)
g. drawStringC'E", width – 10, 32, Graphics.RIGHT I Graphics.BOTTOM)
g. drawString("R", width – 10, 44, Graphics.RIGHT I Graphics.BOTTOM)
g. drawStringC'T", width – 10, 56, Graphics.RIGHT I Graphics.BOTTOM)
g. drawString("I", width – 10, 68, Graphics.RIGHT I Graphics.BOTTOM)
g. drawString ("C", width – 10, 80, Graphics.RIGHT | Graphics.BOTTOM)
g. drawStringC'A", width – 10, 92, Graphics.RIGHT I Graphics.BOTTOM) g.drawString ("L", width – 10, 104, Graphics.RIGHT I Graphics.BOTTOM);
g. drawChar('B', width – 25, 20, Graphics.RIGHT | Graphics.BOTTOM);
g. drawChar(0, width – 25, 32, Graphics.RIGHT I Graphics.BOTTOM);:
g. drawChar('L', width – 25, 44, Graphics.RIGHT I Graphics.BOTTOM);:
g. drawChar ('D', width – 25, 56, Graphics.RIGHT I Graphics.BOTTOM);
}
.
}
Эта демонстрационная программа выбирает, где разместить текстовые строки «Default», «Large», «Medium» и «Small», располагая основные линии ограничивающих прямоугольников. Текст также выравнивается по левому краю. Обратите внимание, что логический OR горизонтальной и вертикальной политик привязки (LEFT | BOTTOM) указывают позицию привязки.
Две строки «BOLD» и «VERTICAL» нарисованы вертикально простым размещением отдельных символов с помощью метода drawChar(). Они определяются сдвигом от правого края дисплея. С помощью политики привязки RIGHT код вычисляет положение правого края ограничивающего прямоугольника, вычитая некоторое количество пикселей из координаты крайнего справа пикселя дисплея.
API Graphics также определяет другую константу, VCENTER, которая действительна только для указания вертикальной политики привязки при размещении изображений. Она недействительна для текста. VCENTER обуславливает то, что вертикальный центр изображения должен быть размещен в координатной точке (х, у). Вы узнаете о работе с изображениями далее в этой главе.
Шрифты. Вы можете выбрать шрифт для любого текста, который вы изобразили в Canvas, как демонстрируется в листинге 6.6. Вы выбираете шрифт, указывая три атрибута шрифта: гарнитура, стиль и размер. Класс javax.microedition.lcdui.Font определяет для каждой из трех категорий константы, показанные в таблице 6.6.
Таблица 6.6. Графические константы, которые определяют атрибуты шрифтов
Константа атрибута – Описание
static int FACE MONOSPACE – Значение атрибута гарнитуры
static int FACE_PROPORTIONAL – Значение атрибута гарнитуры
static int FACE SYSTEM – Значение атрибута гарнитуры
static int STYLE BOLD – Значение атрибута стиля
static int STYLE ITALIC – Значение атрибута стиля
static int STYLE PLAIN – Значение атрибута стиля
static int STYLE UNDERLINED – Значение атрибута стиля
static int SIZE SMALL – Значение атрибута размера
static int SIZE MEDIUM – Значение атрибута размера
static int SIZE LARGE – Значение атрибута размера
Вы должны были заметить, что спецификация MIDP не требует от реализаций предоставления всех этих размеров, стилей и гарнитур. Выводимый шрифт, которым реализация может управлять, будет как можно ближе соответствовать требуемому шрифту.
В отличие от AWT и Swing, вам не придется иметь огромный набор шрифтов и несметное число размеров шрифтов. Более того, поскольку класс Font объявлен final и не имеет конструкторов public, вы не можете организовать его подклассы для определения новых шрифтов. Создатели MIDP решили ограничить число доступных шрифтов с учетом ограничений устройства.
Вам необходимо получить ссылку на текущий объект Font для того, чтобы переслать его в метод Graphics.setFont(). Вы можете получить объект Font, только вызвав один из двух методов static:
Font.getFont(int face, int style, int size)
Font.get Default Font ()
Указанный шрифт будет использоваться во всех последующих операциях по рисованию до тех пор, пока вы вновь его не измените. В листинге 6.6 шрифт был изменен до создания различных текстовых строк или символов для достижения желаемого эффекта.
Отсечение областей для рисования
Когда ваше приложение вызывает метод Display.setCurrent(), он запрашивает реализацию об отображении вашего Displayable. Для объектов Canvas реализация делает ваш компонент текущим отображаемым и вызывает метод вашего класса paint (Graphics g). Реализация генерирует внутреннее событие рисования, которое пересылается в текущий отображаемый элемент. В этом кроется причина того, что метод paint() указан в таблице 6.1 как часть обработки событий API, определяемой Canvas.
Во время отображения некоторая группа пикселей дисплея может быть недействительной или поврежденной. Недействительный или поврежденный пиксель – это тот, который видим в результате предыдущей операции рисования, но не должен быть визуализирован в качестве части текущей операции рисования. Дисплей может быть поврежден другим MID-летом или даже «внешним» приложением – например, приложением по передаче сообщений, которое обновляет дисплей для отображения получения сообщения SMS вашим мобильным телефоном.
Перед тем как приступить к самому рисованию, ваш Canvas обязан стереть все пиксели, появившиеся на экране, которые не должны быть частью его внешнего вида. Вы восстанавливаете экран, обновляя недействительные пиксели.
Вы, несомненно, уже обратили внимание на наличие метода paintClipRect (Graphics g) в листинге 6.3. В листинге 6.7 повторяется этот метод. Это первый код, вызываемый методом paint (Graphics g) каждого приложения. Его цель состоит в удалении всех пикселей, которые были нарисованы предыдущей операцией рисования.
Листинг 6.7. Вы должны стереть все недействительные пиксели, прежде чем рисовать свой компонент. Используйте отсекаемый прямоугольник графического объекта вашего компонента, чтобы определить прямоугольную область, которая содержит все поврежденные пиксели
protected void paintClipRect(Graphics g)
int clipX = g.getClipX (); int clipY = g.getClipY();
int clipH = g.getClipHeight(); int clipW = g.getClipWidth();
int color = g.getColor();
g. setColor(WHITE);
g. fillRect(clipX, clipY, clipW, clipH);
g. setColor(color);
}
Проблема этого метода заключается в том, что он использует отсекаемый прямоугольник объекта Graphics. Отсекаемый прямоугольник является прямоугольной областью, которая содержит все недействительные пиксели экрана. Отсекаемый прямоугольник определяется его отклонением (х, у) от начала координат объекта Graphics, а также его шириной и высотой.
Вы можете получить отсекаемый прямоугольник, вызвав следующие методы Graphics:
int getClipHeight ()
int getClipWidth ()
int getClipX()
int getClipY()
При вызове метода paint (Graphics g) отсекаемый прямоугольник всегда представляет область, которая содержит все поврежденные пиксели дисплея. В случаях, подобных примерам, приведенным в этой главе, где вы заменяете отображение экрана новым, отсекаемый прямоугольник представляет всю область дисплея устройства.
Самый легкий способ «стереть» недействительные пиксели – это перерисовать каждый пиксель в отсекаемом прямоугольнике с помощью цвета фона экрана, таким образом гарантировав, что вы стерли все поврежденные пиксели. Затем вы выполняете операции по рисованию, которые определяются вашим Canvas, с помощью другого цвета.
Обратите внимание, что в листинге 6.7 метод получает и сохраняет текущий цвет дисплея, который представляет цвет ручки, используемый для всех операций рисования. По умолчанию цвет обычно черный в большинстве реализаций. Код затем устанавливает текущий цвет на белый (который обычно является цветом фона) и заполняет отсекаемый прямоугольник белыми пикселями, эффективно «стирая» все поврежденные пиксели. В конце код восстанавливает первоначальный цвет объекта Graphics. Последующие операции по рисованию визуализируют пиксели некоторого цвета, отличающегося от белого, на белом фоне.
В некоторых случаях отсекаемый прямоугольник может представлять некоторую часть дисплея. В этих случаях только некоторая часть дисплея была повреждена. Ваше приложение может выбрать простую перерисовку всего экрана, но ему необязательно делать это. Оно может просто также перерисовать лишь поврежденную область.
Поврежденная область, которая нуждается в перерисовке, является пересечением области, используемой вашим Canvas, и отсекаемым прямоугольником. Вы можете определить, какие из пикселей вашего дисплея относятся к этой области, наложив отсекаемый прямоугольник на область, которую, как вы знаете, ваш Canvas использует для отображения. Метод
void clipRect(int x, int у, int width, int height)
устанавливает отсекаемый прямоугольник как пересечение текущего отсекаемого прямоугольника и прямоугольника, определенного аргументами, – области, используемой вашим Canvas. Ваше приложение может затем вычислить, какие из пикселей относятся к этому новому отсекаемому прямоугольнику, и перерисовать их.
Вызов clipRect () всегда создает отсекаемый прямоугольник меньшего размера. Вы можете также установить любой размер отсекаемого прямоугольника с помощью следующего вызова:
setClipfint x, int у, int width, int height)
Ваш Canvas нуждается в перерисовке только тех пикселей, которые подпадают под область пересечения, поскольку отсекаемый прямоугольник гарантирует включение всех поврежденных пикселей. Конечно, вычисление этой области может быть более сложным, чем простая перерисовка всего Canvas. Но закрашивание только отсекаемого прямоугольника полезно для приложений, которые используют сложную или отнимающую много времени обработку при вычислении того, какие пиксели нужно закрашивать.
Другим стандартным применением отсечения является разработка игр. Стандартное приложение является каркасом, в котором вы хотите переносить фантом, являющийся небольшим изображением или значком. Используя область отсечения, как показано в листинге 6.7, вы рисуете фон области, где фантом расположен в настоящее время, а затем вы рисуете фантом в его новой позиции.
На самом деле на реальном устройстве, которое не поддерживает двойной буферизации, реализация, показанная в листинге 6.7, может производить довольно заметное и разрушительное мерцание экрана при его обновлении. Вы, вероятно, не заметите никакой вспышки лри использовании эмулятора из-за скорости вашего компьютера. В разделе «Двойная буферизация» далее в этой главе вам будет показано, как справиться с этой проблемой.
Рисование – это процесс изменения состояния объекта Graphics. Визуализация – это процесс отображения закрашенных пикселей на экране. Вы никогда не сможете формировать изображение за пределами отсекаемого прямоугольника. Координаты, переданные процедурам рисования, всегда являются интерпретированными по отношению к первоначальному отсекаемому прямоугольнику. Операции по рисованию, которые лежат вне границ отсекаемого прямоугольника, не влияют на визуализацию, они не появляются на экране. Отрицательные значения координат х и у относятся к пикселям, лежащим за пределами отсекаемого прямоугольника.
Хотя вы никогда не сможете формировать изображение за пределами отсекаемого прямоугольника, вы можете рисовать где угодно, даже за пределами отсекаемого прямоугольника. Вы можете даже рисовать за границами обьекта Graphics. Вы можете реализовать панорамирование или перемещение изображения, изменяя координаты х и у начала координат при рисовании.
Преобразование
Как вы уже знаете, точка (х, у) указывает функции рисования место, расположенное относительно точки (0, 0). Точка (0, 0) является началом координат Graphics. Когда вы впервые получите ссылку на Graphics вашего Canvas, его начало координат, точка (О, О), всегда представляет верхний левый угол дисплея устройства.
Преобразование Graphics означает перенос его начала координат. После перемещения начало координат Graphics представляет некоторую точку, отличную от левого верхнего пикселя. Вы переводите начало координат Graphics с помощью метода
void translate(int x, int у)
Аргументы являются координатами точки, которая станет новым началом координат объекта Graphics. Точка (0, 0) теперь является этим новым началом координат. Все операции по рисованию теперь относятся к этому новому началу координат. На рисунке 6.9 показан экран, созданный кодом, описанным в листинге 6.8. Он просто рисует заполненный квадрат в Canvas.
При нажатии на кнопку Go начало координат Graphics переносится, а затем заполненный квадрат перерисовывается. На рисунке 6.10 показан обновленный дисплей после того, как кнопка Go была нажата в первый раз. Обратите внимание, что координаты, переданные вызовам методов рисования в методе paint (Graphics g) не изменились. Причина этого кроется в том, что эти координаты всегда связаны с началом координат Graphics, а не с верхним левым углом области дисплея устройства. Операции по рисованию всегда указываются относительно начала координат Graphics, безотносительно к точке места назначения, которое она представляет.