Платформа J2Me
Шрифт:
Конструктор No-arg.
* /
public DoubleBufferDemo
super;
addCoramand(back); setCommandListener(this); display.setCurrent(this);
if (! isDoubleBufferedO)
{
// Если реализация не использует двойную буферизацию
// автоматически, извлеките Image для того, чтобы мы могли
// получить из него внеэкранный Graphics. Этот Image изменяемый!
// Его размерами являются высота и ширина данного Canvas.
offscreen = Image.createlmage(getWidth ,
getHeight );
autoDoubleBuffered = false;
}
)
protected void paintdipRect (Graphics g)
int clipX = g.getClipX;
ir.t 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);
}
public void paint(Graphics g)
}
Graphics originalG = null;
int width = getWidth; int height = getHeight;
if (!autoDoubleBuffered)
}
//
// новый внеэкранный Graphics из утилиты Image.
originalG = g;
g = offscreen.getGraphics ;
// Очищаем отсекаемый прямоугольник с помощью нового объекта
// Graphics. Таким образом, мы используем двойную буферизацию
// для очистки Canvas, следовательно, избегая мерцания.
// Очистка Canvas является рисованием, как и все другие
// операции по рисованию. paintdipRect (g);
}
else
{
// Очищаем Canvas с первоначальной графикой, поскольку
// реализация не выполняет двойной буферизации автоматически.
paintdipRect (g);
}
for (int x = 0, у = 0; (x < width /2); x = x + 2)
{
g. drawRect(x, y, (width — x) — x, (height — y) — y);
у +1; у +1;
}
// При рисовании изображения содержимое внеэкранного
// контекста Graphics изображения на самом деле копируется
// в контекст Graphics устройства. if (!autoDoubleBuffered)
{
originalG.drawlmage(offscreen, 0, 0,
Graphics.TOP | Graphics.LEFT);
{{
public void commandAction(Command c, Displayable d)
}
if (c == back)
GraphicsDemo.getInstance. display!);
}
}
}
Конструктор содержит первый код, связанный с двойной буферизацией. Нижеприведенный оператор, взятый из безаргументного конструктора DoubleBufferDemo, определяет, поддерживает ли реализация автоматическую двойную буферизацию.
if (!isDoubleEuffered)
{
offscreen = Image.createlmage(getWidth, getHeight);
autoDoubleBuffered = false;
}
Если реализация не поддерживает двойную буферизацию, приложению не нужно выполнять ее. Метод Canvas.IsDoubleBuffered сообщает вам, не выполняет ли реализация двойную буферизацию неявно. Обратите внимание на конструкцию объекта Image. Этот вызов Image, create Image создает изменяемый объект Image. Приложение нуждается в изменяемом Image, потому что оно выполняет рисование в контексте Graphics объекта Image, являющемся нужным вам внеэкранным буфером. Это единственный способ получения дополнительного Graphics в MIDP.
Метод paint содержит остальной код двойной буферизации. Если автоматическая двойная буферизация не осуществляется, приложение должно выполнить ее. Это требует второго графического контекста. Следующий фрагмент метода paint демонстрирует эту идиому
public void paint(Graphics g)
if (!autoDoubleBuffered)
originalG = g;
g = offscreen.getGraphics;
else
{
paintClipRect(g);
}
.
}
Временная переменная хранит ссылку на первоначальный объект Graphics, который представляет графический контекст устройства. Новый графический контекст получается через объект Image, созданный ранее. Этот Graphics связан с Image. Последовательность событий представлена схематично на рисунке 6.11.
Теперь метод paint (Graphics g) выполняет свои операции по рисованию во внеэкранном контексте Graphics. При выполнении он копирует содержимое внеэкранного Graphics в первоначальный контекст Graphics, что в результате формирует изображение на дисплее. Операция копирования совершается с помощью вызова метода Graphics.drawlmage. Этот метод говорит по сути: «Копируй содержимое графического контекста этого аргумента изображения в меня».
Механизм двойной буферизации в MIDP отличается от двойной буферизации Swing. В Swing вы можете выполнять двойную буферизацию операций по рисованию в любом Component, не только в объектах Canvas. Приложения Swing вызывают Java. awt. Component.getGraphics для получения внеэкранного графического контекста. Приложение может рисовать в этом контексте. Оно затем связывает этот внеэкранный графический контекст с самим устройством.
Рисунок 6.11. Левая половина
MIDP не имеет такого вызова. Единственной ссылкой на объект Graphics, которая связана с реальным устройством, является та, что передается методу paint (Graphics g) Canvas.
Вы уже узнали в главе 5, что некоторые компоненты высокоуровневого пользовательского интерфейса MIDP умеют отображать изображения, например, как часть элемента в ChoiceGroup. Объекты Canvas также могут отображать изображения. Кроме рисования базовых геометрических фигур, объект Canvas может «рисовать» изображения с помощью того же контекста Graphics, который он использует для низкоуровневых функций рисования. MIDP поддерживает только формат изображений PNG.
На рисунке 6.12 показано изображение, отображаемое в Canvas. В листинге 6.10 показана исходная программа, создающая изображение, показанное на рисунке 6.12. Структура программы сходна с другими демонстрационными программами Canvas, приведенными в этой главе.
Рисунок 6.12. Canvas может отображать изображение, на самом деле рисуя изображение в контексте Graphics объекта изображения
Листинг 6.10. Чтобы отобразить изображение, Canvas просто «рисует» объект изображения с помощью процедуры рисования изображения объекта Graphics
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.microedition.lcdui.Image;
import Java.io.lOException;
/*
Демонстрирует двойную буферизацию изображений в Canvas.
Изображения автоматически дважды буферизируются.
Эта программа демонстрирует, что вы ничего не должны делать для получения поведения двойной буферизации при отображении изображений.
Однако вам все равно придется провести двойную буферизацию операции, которая рисует фон Canvas, до рисования изображения.
*/
public class DoubleSufferlmageDemo extends Canvas
implements CommandListener
{
// Константа, которая представляет белый цвет.
private static final int WHITE = OxFF «16 I OxFF «8 I OxFF;
private static Command back = new Command ("Back", Command.BACK, 1);
private GraphicsDemo gDemo = GraphicsDemo.getlnstance;
private Display display = Display.getDisplay (gDerno);
// Ссылка на Image, которое отображает этот объект. Image image;
// Переменная, используемая для определения того, осуществляет
// ли реализация автоматическую двойную буферизацию.
// Принимает значение «true», если реализация осуществляет
// автоматическую двойную буферизацию,
«false» в ином случае, private boolean autoDoubleBuffered = true;
/**
Конструктор No-arg.
*/
public DoubleBufferlmageDemo
{
super;
if (!isDoubleBuffered)
{
autoDoubleBuffered = false;
}
// Создайте изображение PNG. Изображение «нарисовано» в
// изменяемом объекте Image, который имеет свой собственный
// внеэкранный Graphics. Мы сейчас создаем изображение в
// конструкторе, вместо метода paint ,
//так что оно создается только один раз. try
}
image = Image.createlraage("/bottle80x80.png");
}
catch (lOException ioe)
{
System.out.println(ioe.getMessage); ioe.printStackTrace;
}
addCommand(back); setCommandListener(this); display.setCurrent (this);
}
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. fillRecc(clipX, clipY, clipW, clipH);
g. setColor (color);
/**