Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Секреты программирования для Internet на Java

.pdf
Скачиваний:
181
Добавлен:
02.05.2014
Размер:
3.59 Mб
Скачать

подход, чтобы заодно проиллюстрировать возможность распределить обработку событий между несколькими методами (что позволяет иногда упростить код). Например, можно завести обработчик событий mouseDown, перехватывающий только события, связанные с мышью, а всю остальную обработку событий вынести в метод handleEvent:

public boolean action(Event evt, Object arg) { if (evt.target instanceof Choice) {

((CardLayout)cards_panel.getLayout()).show(cards_panel,(String)arg); // * см. объяснение ниже

return true;

}

return false;

}

} // конец апплета

Строка, после которой стоит комментарий со звездочкой, может показаться слишком запутанной, хотя функция ее в действительности проста: этот оператор обращается к выпадающему списку, выясняет, какой из его элементов выбран в данный момент, и передает этот выбранный элемент непосредственно методу show, где он трактуется как метка той панели, которую нужно вывести в cards_panel. Значение выбранного элемента передается в переменной arg. Помимо метода show, с менеджером CardLayout можно также пользоваться методами next и previous, позволяющими выводить соответственно следующий и предыдущий элемент из тех, что определены в данном контейнере. Этот метод можно, например, использовать при последовательном выводе серии компонентов или для перемещения по цепочке элементов с помощью кнопок типа "Вперед" и "Назад".

Точное расположение: GridBagLayout

Менеджер GridBagLayout - самый сложный и эффективный из менеджеров размещения. В тех случаях, когда ваш интерфейс содержит много компонентов, над расположением которых хочется иметь больше контроля, чем могут обеспечить другие менеджеры размещения, следует использовать GridBagLayout. Предположим, что дизайнер рекомендует для апплета пересчета денежных сумм следующую компоновку: поля вывода коэффициента пересчета и полоса прокрутки для его изменения должны быть расположены на одной горизонтальной линии, ниже по центру - поле ввода исходного значения, а поле для вывода результата должно занимать всю нижнюю часть апплета (рис. 8-8). Такого расположения можно достигнуть только с помощью менеджера GridBagLayout. При этом на расположение каждого компонента сначала налагаются определенные ограничения, и только затем этот компонент добавляется к апплету. Менеджер GridBagLayout располагает компоненты на экране с учетом этих ограничений.

Ⱦɚɧɧɚɹ ɜɟɪɫɢɹ ɤɧɢɝɢ ɜɵɩɭɳɟɧɚ ɷɥɟɤɬɪɨɧɧɵɦ ɢɡɞɚɬɟɥɶɫɬɜɨɦ %RRNV VKRS Ɋɚɫɩɪɨɫɬɪɚɧɟɧɢɟ ɩɪɨɞɚɠɚ ɩɟɪɟɡɚɩɢɫɶ ɞɚɧɧɨɣ ɤɧɢɝɢ ɢɥɢ ɟɟ ɱɚɫɬɟɣ ɁȺɉɊȿɓȿɇɕ Ɉ ɜɫɟɯ ɧɚɪɭɲɟɧɢɹɯ ɩɪɨɫɶɛɚ ɫɨɨɛɳɚɬɶ ɩɨ ɚɞɪɟɫɭ piracy@books-shop.com

Рис. 8.8.

Пример 8-6. Апплет, использующий менеджер GridBagLayout. public class LayoutGridBag extends Applet {

float conversion_ratio = 1.5f; TextField field1 = new TextField(5); TextArea field2 = new TextArea(4,20); TextField ratioField = new TextField(5);

Scrollbar ratioScrollBar = new Scrollbar( Scrollbar.HORIZONTAL, 150, 25, 50, 250 );

GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints Con = new GridBagConstraints();

public void init() { setLayout(gridbag);

setFont(new Font("Helvetica", Font.PLAIN, 12)); setBackground(Color.gray); ratioField.setEditable(false); field1.setEditable(true); field2.setEditable(false); ratioField.setText("1.50"); field1.resize(field1.preferredSize()); field2.resize(field2.preferredSize()); ratioField.resize(ratioField.preferredSize());

ratioScrollBar.resize(ratioScrollBar.preferredSize());

Con.weightx=1.0;

Con.weighty=1.0;

Con.anchor = GridBagConstraints.CENTER; Con.fill = GridBagConstraints.NONE; Con.gridwidth=GridBagConstraints.RELATIVE; gridbag.setConstraints(ratioField, Con); add(ratioField);

Con.gridwidth = GridBagConstraints.REMAINDER;

Прежде всего создаются новые экземпляры менеджера размещения GridBagLayout и класса gridBagContraints. В качестве менеджера размещения вызывается GridBag, который является экземпляром GridBagLayout. Если не менять значения weightx и weighty, входящие в класс gridBagContraints (их значения по умолчанию равны нулю), то все компоненты будут тяготеть к центру, тогда как в данном случае нам нужно совсем не это. Значение по умолчанию параметра fill равно BOTH, что означает, что компоненты будут растягиваться по обеим координатам. Здесь, однако, нам не нужно, чтобы полоса прокрутки, поле ratioField и поле ввода растягивались,

www.books-shop.com

поэтому для них параметр fill устанавливается в NONE. Напротив, поле для выходного значения должно быть растянуто насколько возможно, поэтому для него параметру fill присваивается прежнее значение BOTH. Для параметра anchor используется значение CENTER, благодаря чему все компоненты размещаются в центрах отведенных для них областей. Поскольку в момент добавления поле ratioField должно располагаться после последнего элемента в своем ряду, для этого компонента параметр gridwidth устанавливается в RELATIVE. Для полосы прокрутки ratioScroolBar, которая должна быть последней в ряду, значение параметра gridwidth устанавливается равным REMAINDER.

В этом примере один и тот же экземпляр gridBagContraints используется несколько раз, поэтому перед повторным использованием даже тем ограничителям, для которых нас устраивает значение по умолчанию, необходимо явным образом присвоить нужные значения. Наоборот, другие параметры имеют во всех случаях одинаковое значение, и с ними перед повторным использованием экземпляра gridBagContraints ничего делать не нужно. Если бы мы создавали по экземпляру gridBagContraints для каждого компонента, то во всех этих экземплярах пришлось бы устанавливать одни и те же параметры в одни и те же значения. Поэтому более экономный подход - создать один экземпляр этого класса и использовать его для всех компонентов:

gridbag.setConstraints(ratioScrollBar, Con); add(ratioScrollBar); Con.gridwidth=GridBagConstraints.REMAINDER; gridbag.setConstraints(field1, Con); add(field1); Con.gridy=GridBagConstraints.RELATIVE; Con.fill = GridBagConstraints.BOTH; Con.gridwidth=GridBagConstraints.REMAINDER; Con.gridheight=GridBagConstraints.REMAINDER; gridbag.setConstraints(field2, Con); add(field2);

} // конец метода init

Поле для вывода результата должно занимать все отведенное для него место, поэтому значение fill для него устанавливается равным BOTH, а переменным gridwidth и gridheight присваивается значение REMAINDER. Следующие две строки устанавливают введенные ограничения для поля field2 и добавляют это поле к апплету. Остальная часть кода выглядит так же, как в предыдущих примерах. Теперь вы можете поэкспериментировать со значениями ограничителей, знакомясь с возможностями метода GridBagLayout и совершенствуя интерфейс нашего апплета.

Добавление меню: CardLayout

Давайте вернемся еще раз к примеру, в котором использовался менеджер размещения CardLayout, и заменим в нем выпадающий список на меню (рис. 8-9). Как и прежде, органы управления этого апплета собраны в две панели, отображаемые в окне апплета по очереди. Разобравшись с этим простым примером, вы можете экспериментировать с меню дальше.

Рис. 8.9.

Пример 8-7. Апплет, использующий меню. import java.awt.*;

import java.applet.Applet;

public class Menu1 extends Applet { public void init(){

new Menu_Frame();

}

www.books-shop.com

} // конец Menu1

// создаем новый экземпляр класса Menu_Frame class Menu_Frame extends Frame {

float conversion_ratio = 1.5f; TextField field1 = new TextField(15); TextArea field2 = new TextArea(4,20); TextField ratioField = new TextField(5);

Scrollbar ratioScrollBar = new Scrollbar( Scrollbar.HORIZONTAL, 150, 25, 50, 250 );

Panel cards_panel; public Menu_Frame() {

setLayout(new BorderLayout()); MenuBar Bar = new MenuBar(); Menu m = new Menu("Operation");

m.add(new MenuItem("Adjust Ratio")); m.add(new MenuItem("Calculate")); Bar.add(m);

setMenuBar(Bar);

Первое, что делается в примере 8-7, - создается новое меню. Для этого создается экземпляр класса MenuBar под названием Bar и экземпляр класса Menu под именем m. Затем созданное меню заполняется командами, добавляется к панели Bar, и, наконец, с помощью метода setMenuBar готовая панель добавляется в апплет.

setFont(new Font("Helvetica", Font.PLAIN, 12)); setBackground(Color.gray); ratioField(setEditable(false)); field1.setEditable(true); field2.setEditable(false); ratioField.setText("1.50"); field1.resize(field1.preferredSize()); field2.resize(field2.preferredSize());

ratioField.resize(ratioField.preferredSize());

ratioScrollBar.resize(ratioScrollBar.preferredSize());

Приведенный ниже фрагмент состоит из тех же основных элементов, что и первый пример с менеджером размещения CardLayout. Никаких изменений здесь не требуется; нужно лишь сделать так, чтобы метки панелей совпадали с текстом соответствующих команд меню. На этом совпадении основана процедура смены панелей в методе handleEvent:

cards_panel = new Panel(); cards_panel.setLayout(new CardLayout()); Panel ratio_panel = new Panel();

Panel calculate_panel = new Panel(); ratio_panel.add(ratioField); ratio_panel.add(ratioScrollBar); calculate_panel.add(field1); calculate_panel.add(field2); cards_panel.add("Adjust Ratio", ratio_panel); cards_panel.add("Calculate", calculate_panel); add("Center", cards_panel);

resize(250,300);

pack();

show(); } // Menu_Frame

public void convert() {

float currency1, currency2;

String InputString = field1.getText(); field1.setText("");

currency1 = Float.valueOf(InputString).floatValue(); currency2 = conversion_ratio * currency1;

String OutputString ="$" + InputString + " = " + "#" + Float.toString(currency2) + "\n";

www.books-shop.com

field2.appendText(OutputString); } //convert

public boolean handleEvent(Event evt) { if (evt.target == ratioScrollBar)

{

int in;

in = ratioScrollBar.getValue(); conversion_ratio = in/100f;

ratioField.setText(Float.toString(conversion_ratio));

}

if (evt.target == field1)

{

char c=(char)evt.key; if (c == '\n')

{

convert(); return true;

}

else { return false; }

}

if ((evt.id == Event.ACTION_EVENT) && (evt.target==m) )

{

((CardLayout)cards_panel.getLayout()).show(cards_panel,(String)evt.arg

);

return true;

}

if (evt.id == Event.WINDOW_DESTROY) { dispose();

return true;

}

return false;

}

} // конец Menu_Frame

Метод handleEvent обрабатывает событие выбора команды из меню. Этот метод ждет события ACTION_EVENT, пунктом назначения (target) которого является требуемое меню. Если эти условия выполнены, метод проверяет, какая именно команда была выбрана, по значению параметра evt.arg и отображает соответствующую панель в cards_panel. Не забудьте также о необходимости обработки события WINDOW_DESTROY.

Что дальше?

Вэтой главе мы познакомились с более сложными приемами построения интерфейса пользователя. Применяя методики, рассмотренные в этой главе, и базовые элементы из главы 7, вы сможете создавать апплеты с богатыми, разнообразными интерфейсами. В основе построения интерфейса в Java лежат понятия контейнера и менеджера размещения. Этими же инструментами мы будем пользоваться в учебной части книги, где мы займемся разработкой нескольких полнофункциональных программ, оформленных в виде апплетов.

Вследующей главе рассмотрим классы Java, позволяющие работать в апплетах с графической информацией и выводить изображения.

www.books-shop.com

Глава 9

Графика и изображения

Рисование при помощи класса Graphics Рисование контурных объектов Рисование заполненных объектов Текст и рисунки

Использование класса Image Импорт изображений

Использование класса MediaTracker Создание изображений Интерфейсы для асинхронных изображений Манипулирование изображениями

В последних двух главах вы изучали создание мощного и привлекательного интерфейса пользователя. Эта глава обучит вас, как выводить и управлять графическими изображениями, которые могут увеличить популярность ваших Java-апплетов и программ.

Класс Graphics, входящий в иерархию java.awt, дает нам множество методов для вывода геометрических форм и размещения текста в области двумерных рисунков (которая связана с видимым объектом Component или Image). Функциональные возможности пакета близки к простому графическому редактору, подобному Microsoft Paintbruish. Пакет java.awt.image, отличный от пакета java.awt и класса java.awt.Image (хотя близко связан с обоими), позволяет взаимодействовать с изображениями на уровне байтов, создавая изображения при помощи заданных программистом алгоритмов. Кроме того, этот пакет предлагает мощные инструментальные средства для обработки уже существующих изображений.

СОВЕТ Фрагменты кода, приводимые в качестве примеров в этой главе, помещены на диск CDROM, прилагаемый к книге. Этим диском могут пользоваться те из читателей, кто работает с Windows 95/NT или Macintosh; пользователи UNIX должны обращаться к Web-странице Online Companion, на которой собраны сопроводительные материалы к этой книге (адрес http://www.vmedia.com/java.html).

Рисование при помощи класса Graphics

Класс Graphics позволяет рисовать на двумерном холсте с помощью стандартных графических примитивов. Обратите внимание, что вы не можете создавать объект Graphics самостоятельно, так как единственый конструктор определен с модификатором private. Обычно объект Graphics или связан с классом Component, с которым вы работаете, и передан вам, как в случае использования метода paint класса Component, или получен явно методом getGraphics класса

Component.

Класс Image также осуществляет метод getGraphics, который возвращает ссылку на объект Graphics, связанный с Image. Эта методика кратко обсуждалась в главе 5, "Апплет в работе".

Рисование контурных объектов

Так как в классе Graphics очень много методов, мы разобьем их на три группы и обсудим поочередно. Первый раздел содержит все методы, связанные с рисованием контурных (незаполненных) рисунков заданным по умолчанию цветом. Эти методы перечислены в табл. 9-1.

Таблица 9-1. Методы рисования класса Graphics для работы с контурными формами

Метод Описание

drawLine (int, int, Выводит линию от позиции, заданной первыми двумя целыми числами int, int) (координаты X и Y), до позиции, обозначенной вторыми двумя целыми

числами.

drawRect (int, int, Выводит прямоугольник. Первые два целых числа указывают верхний левый int, int) угол прямоугольника, а последние два целых числа указывают ширину и

высоту.

draw3DRect (int, Выводит подсвеченный трехмерный прямоугольник. Сам прямоугольник

www.books-shop.com

int, int, int,

задан первыми четырьмя целыми числами, как и в методе drawRect, а

boolean)

булевская переменная указывает, должен ли прямоугольник быть поднят над

 

фоном.

drawRoundRect (int, Выводит прямоугольник со скругленными углами, вписанный в нормальный int, int, int, int, int) прямоугольник, заданный первыми четырьмя целыми числами. Последние

два целых числа указывают ширину и высоту дуги для углов. Ширина и высота дуги определяет диаметр дуги по оси X или Y. Большие значения дают более гладкие закругления.

drawOval (int, int, Выводит овал, вписанный в прямоугольник, определенный четырьмя целыми int, int) числами.

drawArc (int, int, Выводит дугу, вписанную в прямоугольник, определенный первыми четырьмя int, int, int, int) целыми числами. Последние два целых числа указывают начальные и

конечные углы, измеряемые в градусах. Отсчет углов начинается от центра правой стороны графической области. Положительные значения указывают направление вращения против часовой стрелки, а отрицательные, соответственно, - по часовой стрелке.

drawPolygon (int [], Выводит многоугольник. Целочисленные массивы содержат координаты X и Y int [], int) для точек, составляющих многоугольник, а целочисленный параметр

указывает общее количество точек.

drawPolygon Выводит многоугольник. Многоугольник задан параметром Polygon. (Polygon)

У методов класса Graphics есть несколько особенностей, которые вы должны знать. Метод draw3DRect выводит прямоугольник, который во всех отношениях идентичен прямоугольнику, получаемому методом drawRect, независимо от того, поднят он или нет. Возможно, что это ошибка, которая будет исправлена в более поздних версиях Java API, а теперь, если вы хотите рисовать трехмерные прямоугольники, вы должны будете вывести их непосредственно. Метод drawArc очень похож на метод drawOval - фактически при вызове drawOval(0, 0, X, Y) и drawArc(0, 0, X, Y, 0, 360) будет получено одно и то же изображение. Использование метода drawArc позволяет запрашивать вывод только некоторой части овала.

Рисование заполненных

Вы можете заполнять краской области экрана различной геометрической формы. Для каждого из контурных методов рисования, перечисленных в табл. 9-1, кроме drawArc и drawLine, есть соответствующий метод заполнения рисунка. Просто замените слово draw на слово fill, и вы получите новую таблицу методов. Подобно методу draw3DRect, метод fill3DRect выводит прямоугольник точно так же, как обычный метод fillRect.

В следующем простом примере мы выведем две линии из противоположных углов экрана, прямоугольник со скругленными углами, центрированный овал и центрированную дугу и заполним центр экрана серым скругленным прямоугольником. Этот пример иллюстрирует использование контурных и заполняющих методов класса Graphics. Снимок экрана показан на рис. 9-1.

www.books-shop.com

Рис. 9.1.

Пример 9-1. Простой графический апплет. import java.applet.*;

import java.awt.*;

public class GraphicsApplet extends Applet { public void init() {

resize(250,250);

setBackground(Color.white);

}

public void paint(Graphics g) { g.setColor(Color.darkGray); g.drawLine(0,0,250,250); g.drawLine(0,250,250,0); g.drawRoundRect(0,0,250,250,50,50); g.drawOval(0,50,250,150); g.drawArc(75,75,100,100,0,180); g.setColor(Color.gray); g.fillRoundRect(100,100,50,50,25,25);

}

}

Текст и рисунки

Класс Graphics позволяет выводить некоторые негеометрические объекты, а именно изображения и текст в форме строк, символов и байтовых массивов. Изображения, как мы видели в главе 5, вписываются в прямоугольники на нашем объекте Graphics, но фактически представляют собой сложное изображение, которое было бы трудно или невозможно сделать, используя методы рисования и заполнения, обеспечиваемые классом Graphics.

Методы для вывода текста и изображений перечислены в табл. 9-2. Для них нет дополнительных заполняющих методов.

Таблица 9-2. Методы класса Graphics для вывода текста и изображений

Метод Описание

drawString(String, int, Выводит данную строку текущим шрифтом в определенном int) расположении.

drawChars(char[], int, Преобразует символьный массив, переданный как первый параметр, в int, int, int) строку и выводит ее в месте, определенном последними двумя целыми

числами. Первые два целых числа указывают начальное значение индекса для массива и число символов, которые будут преобразованы.

drawBytes(byte[], int, Выводит массив типа byte тем же самым способом, как и метод int, int, int) drawChars.

drawImage(Image, int, Выводит данное изображение в месте, определенном двумя целыми

www.books-shop.com

int, ImageObserver)

числами. Параметр lmageObserver указывает класс, который будет

 

наблюдать за данным изображением, чтобы принимать и вывести

 

изображение, когда передача данных закончена. Этот интерфейс будет

 

обсуждаться позже в разделе "Импортирование и создание

 

изображений".

drawImage(Image, int,

Данное изображение выводится в месте, определенном двумя целыми

int, Color,

числами, со сплошной заливкой фона заданным цветом.

ImageObserver)

 

drawImage(Image, int,

Изображение помещается в прямоугольник, заданный четырьмя целыми

int, int, int,

числами. В случае необходимости изображение будет масштабировано,

ImageObserver)

чтобы приспособить его к прямоугольнику.

Изменение класса Graphics

Ряд методов позволяет вам изменять функциональные возможности класса Graphics. Вы можете менять заданный по умолчанию цвет и шрифт, а также копировать и ограничивать области экрана. Эти методы перечислены в табл. 9-3.

 

Таблица 9-3. Другие методы класса Graphics

Метод

Описание

Graphics create()

Создает новый объект Graphics, который является копией текущего.

Graphics create(int,

Создает новый объект Graphics, который ограничен прямоугольником,

int, int, int)

заданным четырьмя целыми числами. Любые изменения, сделанные в

 

объекте Graphics, будут отражены в заданной прямоугольной области.

Color getColor()

Возвращает текущий цвет рисунка.

setColor(Color)

Устанавливает текущий цвет рисунка.

setPaintMode()

Устанавливает режим закраски, чтобы всегда красить заданным по

 

умолчанию цветом.

setXORMode(Color)

Устанавливает режим закраски заменой заданного по умолчанию цвета

 

другим цветом. При закрашивании пикселы этого цвета будут заменены на

 

пикселы другого цвета и, в свою очередь, пикселы второго цвета будут

 

заменяться на пикселы первого. Изменение остальных пикселов

 

предсказать нельзя. Однако, если вы закрасите их дважды при активности

 

XORMode, они будут сброшены к своим первоначальным цветам. Этот

 

метод может быть полезен для высвечивания (увеличения яркости) или

 

рисования простых мигающих картинок.

Font getFont()

Возвращает текущий шрифт.

setFont(Font)

Устанавливает текущий шрифт.

FontMetrics

Возвращает объект FontMetrics, связанный с текущим шрифтом.

getFontMetrics()

 

FontMetrics

Возвращает объект FontMetrics, связанный с определенным шрифтом.

getFontMetrics(Font)

 

clipRect(int, int, int,

Устанавливает прямоугольник ограничения, заданный четырьмя целыми

int)

числами, для рисования в нем объекта Graphics. Когда прямоугольник

 

ограничения установлен, никакое закрашивание не будет выполняться вне

 

этого прямоугольника.

Rectangle

Возвращает прямоугольник ограничения как объект Rectangle.

getClipRect()

 

copyArea(int, int, int,

Копирует прямоугольник, заданный первыми четырьмя целыми числами.

int, int, int)

Расстояние, на которое нужно переместить его по осям X и Y, задано

 

последними двумя целыми числами.

dispose()

Делает этот объект Graphics непригодным для использования.

Использование класса Image

Хотя методы, предлагаемые классом Graphics, достаточны для создания простых графических изображений, например столбцовых диаграмм или графических меню, они не позволяют вам выполнять сложные графические операции, непосредственно управляя конкретными пикселами. Чтобы сделать это, вы должны использовать класс Image. Объекты Image полезны также тем, что

www.books-shop.com

они обеспечивают удобный непротиворечивый интерфейс для работы с изображениями, импортируемыми из файлов в одном из известных графических стандартов. В этом разделе мы обсудим то, как изображения действительно работают, и асинхронную работу с изображениями, то есть с изображениями, чьи данные недоступны сразу.

Класс Image, часть пакета java.awt, дает несколько методов, при помощи которых можно запрашивать информацию об изображении, например его ширину или высоту. Эти методы перечислены в табл. 9-4.

 

Таблица 9-4. Методы класса lmage

Метод

Описание

Graphics getGraphics()

Возвращает объект Graphics, связанный с изображением.

int

Возвращает высоту изображения, если она известна. Если высота

getHeight(ImageObserver)

неизвестна, что может быть в случае, если изображение еще не

 

получено, этот метод возвращает -1, и данному lmageObserver будет

 

сообщено, когда высота станет известна.

int getWidth(ImageObserver) Возвращает ширину изображения, если она известна. Если ширина неизвестна, этот метод возвращает -1, и данному lmageObserver будет сообщено, когда ширина станет известной.

Object getProperty(String,

Запрашивает значение свойства, заданного параметром String.

ImageObserver)

Например, имя "comments" используется, чтобы сохранить

 

комментарий, содержащий текстовое описание изображения. Если

 

запрошенное свойство не определено для этого изображения, этот

 

метод возвратит объект UndefinedProperty. Если запрошенное

 

свойство не доступно, но имеется (как в случае, если изображение

 

еще не получено), этот метод возвратит пустой указатель, и данному

 

lmageObserver будет сообщено, когда свойство станет известно.

ImageProducer getSource()

Возвращает ImageProducer, который произвел пикселы для этого

 

изображения.

Flush()

Очищает все ресурсы, используемые текущим изображением,

 

включая все сохраненные данные о пикселах. Если это изображение

 

используется снова, оно снова должно быть создано или загружено.

ImageObserver и ImageProducer связываются с помощью интерфейса, упомянутого в табл. 9-4, и используются Java API, чтобы позволить программистам работать с изображениями, чьи данные еще не полностью доступны. Мы обсудим эти интерфейсы в разделе "Интерфейсы для асинхронных образов" ниже в этой главе. Вспомните, что класс Component реализует интерфейс ImageObserver так, что всякий раз, когда вы должны передать ImageObserver как параметр, вы можете передавать ссылку на ваш работающий Component.

Импорт изображений

В главе 5, "Апплет в работе", мы говорили о том, как загрузить изображения из сетевого файлового сервера с помощью URL. Одна из проблем, с которой мы столкнулись при загрузке изображений, состояла в том, что фактически изображение не загружалось до тех пор, пока мы сначала не отобразили его с помощью метода drawImage. Это поведение было особенно значимо, когда мы создали мультипликацию, используя изображения, загруженные через URL. Эта проблема важна не только для изображений, загружаемых из сети, - многие изображения создаются с использованием сложных математических формул, для вычисления которых может потребоваться длительное время. Разработчики Java API в фирме Sun решили позволить программистам начинать использовать изображения в программах прежде, чем загрузка или процесс вычисления для данного изображения будут фактически завершены. Это может быть очень полезно, поскольку вам не придется ждать весь пакет из нескольких изображений перед их выводом; вы можете запрашивать их вывод, когда они готовы для вывода, и ваша программа будет продолжать работу без ожидания.

Использование класса MediaTracker

Хотя обычно удобно иметь изображения, доступные для использования прежде, чем они полностью загружены, бывают ситуации, когда желательно приостановить работу программы, пока данные не будут полностью получены. Как мы видели в главе 5, мультипликация, состоящая из ряда изображений, будет выглядеть очень обрывистой и расплывчатой, пока не будут доступны все изображения. Самым лучшим в этом случае было бы, вероятно, ждать

www.books-shop.com