Апплет HelloWorld в окне Internet Explorer
Рисунок 14.1. Апплет HelloWorld в окне Internet Explorer
В этом простом примере можно заметить еще две особенности апплетов. Во-первых, размер апплета задается не в нем, а в теге <applet>. Это очень удобно, можно менять размер апплета, не компилируя его заново. Можно организовать апплет невидимым, сделав его размером в один пиксел. Кроме того, размер апплета разрешается задать в процентах по отношению к размеру окна браузера, например,
<applet code = "HelloWorld.class" width = "100%" height = "100%">
Во-вторых, как видно на Рисунок 14.1, у апплета серый фон. Такой фон был в первых браузерах, и апплет не выделялся из текста в окне браузера. Теперь в браузерах принят белый фон, его можно установить обычным для компонентов методом setBackground(Color.white), обратившись к нему в методе init ().
В состав JDK любой версии входит программа appietviewer. Это простейший браузер, предназначенный для запуска апплетов в целях отладки. Если под рукой нет Internet-браузера, можно воспользоваться им. Appietviewer запускается из командной строки:
appietviewer HelloWorld.html
На Рисунок 14.2 appietviewer показывает апплет HelloWorld.
Апплет HelloWorld в окне программы appietviewer
Рисунок 14.2. Апплет HelloWorld в окне программы appietviewer
Приведем пример невидимого апплета. В нижней строке браузера — строке состояния (status bar) — отражаются сведения о загрузке файлов. Апплет может записать в нее любую строку str методом showstatus(string str). В листинге 14.3 приведен апплет, записывающий в строку состояния браузера "бегущую строку", а в листинге 14.4 — соответствующий HTML-файл.
Апплет с измененным шрифтом
Рисунок 14.4. Апплет с измененным шрифтом
Правила хорошего тона рекомендуют описать параметры, передаваемые ап-плету, в виде массива, каждый элемент которого — массив из трех строк, соответствующий одному параметру. Данная структура представляется в виде "имя", "тип", "описание". Для нашего примера можно написать:
String!][] pinfo = {
{"fontName", "String", "font name"},
{"fontStyle", "int", "font style"},
{"fontsize", "int", "font size"}
};
Затем переопределяется метод getParameterinfoO, возвращающий указанный массив. Это пустой метод класса Applet. Любой объект, желающий узнать, что передать апплету, может вызвать этот метод. Для нашего примера переопределение выглядит так:
public String[][] getParameterlnfо(){
return pinfo;
}
Кроме того, правила хорошего тона предписывают переопределить метод getAppletinfо (), возвращающий строку, в которой записано имя автора, версия апплета и прочие сведения об апплете, которые вы хотите предоставить всем желающим. Например:
public String getAppletlnfo(){
return "MyApplet v.1.5 P.S.Ivanov";
}
Посмотрим теперь, какие еще параметры можно задать в теге <appiet>.
Апплет создающий окно
Рисунок 14.3. Апплет, создающий окно
Замечание
Замечание
Браузеры помещают загруженные апплеты в свой кэш, поэтому после щелчка кнопкой мыши по кнопке Refresh или Reload запускается старая копия апплета из кэша Для загрузки новой копии надо при щелчке по кнопке Refresh в IE (Internet Explorer) держать нажатой клавишу <Ctrl>, а при щелчке по кнопке Reload в NC (Netscape Communicator) — клавишу <Shift> Иногда и это не помогает. Не спасает даже перезапуск браузера. Тогда следует очистить оба кэша-и дисковый, и кэш в памяти. В IE это выполняется кнопкой Delete Files в окне, вызываемом выбором команды Tools | Internet Options. B NC необходимо открыть окно Cache командой Edit | Preferences | Advanced.
При запуске прилбжения интерпретатором java из командной строки в него можно передать параметры в виде аргумента метода main (string n args). В апплеты также передаются параметры, но другим путем.
Изображение и звук
Изображение и звук
Изображение в Java — это объект класса image, представляющий прямоугольный массив пикселов. Его могут показать на экране логические методы drawimageo класса Graphics. Мы рассмотрим их подробно в следующей главе, а пока нам понадобятся два логических метода:
drawlmage(Image img, int x, int y, ImageObserver obs)
drawImage(Image img, int x, int y, int width, int height,
ImageObserver obs)
Методы начинают рисовать изображение, не дожидаясь окончания загрузки изображения img. Более того, загрузка не начнется, пока не вызван метод drawlmage(). Методы возвращают false, пока загрузка не закончится.
Аргументы (х, у) задают координаты левого верхнего угла изображения img; width и height — ширину высоту изображения на экране; obs — ссылку на объект, реализующий интерфейс ImageObserver, следящий за процессом загрузки изображения. Последнему аргументу можно дать значение this.
Первый метод задает на экране такие же размеры изображения, как и у объекта класса image, без изменений. Получить эти размеры можно методами getWidth(), getHeight{) класса Image.
Интерфейс ImageObserver, реализованный классом Component, а значит, и классом Applet, описывает только один логический метод imageUpdate (),
выполняющийся при каждом изменении изображения. Именно этот метод побуждает перерисовывать компонент на экране при каждом его изменении. Посмотрим, как его можно использовать в процессе загрузки файлов из Internet.
Класс MediaTracker
Класс MediaTracker
Сначала конструктором MediaTracker (Component comp) создается объект класса для указанного аргументом компонента. Аргумент конструктора чаще всего this.
Затем методом addlmagef Image img, int id) регистрируется Изображение img под порядковым номером id. Несколько изображений можно зарегистрировать под одним номером.
После ЭТОГО логическими методами checkID(int id), checkID(int id, boolean load) и checkAii () проверяется, загружено ли изображение с порядковым номером id или все зарегистрированные изображения. Методы возвращают true, если изображение уже загружено, false — в противном случае. Если аргумент load равен true, то производится загрузка всех еще не загруженных изображений.
Методы statusID(int id), statusID(int id, boolean load) и statusALL возвращают целое число, которое можно сравнить со статическими константами COMPLETE, ABORTED, ERRORED.
Наконец, методы waitForID(int id) и waitForAll() ожидают окончания загрузки изображения.
В следующей главе в листинге 15.5 мы применим эти методы для ожидания загрузки изображения.
Изображение, находящееся в объекте класса image можно создать непосредственно по пикселам, а можно получить из графического файла, типа GIF или JPEG, одним из двух методов класса Applet:
getimage(URL address) — задается URL-адрес графического файла; getImage(URL address, String fileName) — задается адрес каталог address и имя графического файла filename .Аналогично, звуковой файл в апплетах Представляется в виде объекта, реализующего интерфейс Audiociip, и может быть получен из файла типа AU, AIFF, WAVE или MIDI одним из трех методов класса Applet с такими же аргументами:
getAudioClip(URL address)
getAudioClip(URL address, String fileName)
newAudioClip(URL address)
Последний метод статический, его можно использовать не только в апплетах, но и в приложениях.
Интерфейс Audioclip из пакета java. applet очень прост. В нем всего три метода без аргументов. Метод play () проигрывает мелодию один раз. Метод loop () бесконечно повторяет мелодию. Метод stop о прекращает проигрывание.
Этот интерфейс реализуется браузером. Конечно, перед проигрыванием звуковых файлов браузер должен быть связан со звуковой системой компьютера.
В листинге 14.9 приведен простой пример загрузки изображения и звука из файлов, находящихся в том же каталоге, что и HTML-файл. На Рисунок 14.5 показано, как выглядит изображение, увеличенное в два раза.
Апплет HelloWorld
Листинг 14.1. Апплет HelloWorld
import j ava.awt.*;
import j ava.applet.*;
public class HeiioWorid extends Applet{
public void paint(Graphics g){
g.drawstring("Hello, XXI century World
1
", 10, 30);
}
}
Эта программа записывается в файл HelloWorld.java и компилируется как обычно: javac HelloWorld.java
Компилятор создает файл HelloWorkLclass, но воспользоваться для его выполнения интерпретатором java теперь нельзя — нет методаjnainо. Вместо интерпретации надо дать указание браузеру для запуска апплета.
Все указания браузеру даются пометками,
тегами
(tags), на языке HTML (HyperText Markup Language). В частности, указание на запуск апплета дается в теге <applet>
. В нем обязательно задается имя файла с классом апплета параметром code, ширина width и высота height панели апплета в пикселах. Полностью текст HTML для нашего апплета приведен в листинге 14.2.
Файл HTML для загрузки апплета HelloWorid
Листинг 14.2. Файл HTML для загрузки апплета HelloWorid
<html>
<head>
<title>
Applet</title>
</head>
<body>
Ниже выполняется апплет.<br>
<applet code = "HeiioWorid.class" width = "200" height = "100">
</applet>
</body>
</html>
Этот текст заносится в файл с расширением html или htm, например. Hel-loWorld.html. Имя файла произвольно, никак не связано с апплетом или классом апплета.
Оба файла — HelloWorld.html и HelloWorld.class — помещаются в один каталог на сервере, и файл HelloWorld.html загружается в браузер, который может находиться в любом месте Internet. Браузер, просматривая HTML-файл, выполнит тег <appiet>
и загрузит апплет. После загрузки апплет появится в окне браузера, как показано на рис, 14.1.
Бегущая строка в строке состояния браузера
Листинг 14.3. Бегущая строка в строке состояния браузера
// Файл RunningString.Java
import j ava.awt.*;
import j ava.applet.*;
public class RunningString extends Applet{
private Boolean go;
public void start(){
go = true;
sendMessage("Эта строка выводится апплетом");
}
public void sendMessage(String s){
String s1 = s+" ";
while(go){
showStatus(s);
try{
Thread.sleep(200);
}catch(Exception e){}
s = s1.substring(l)+s.charAt(0);
s1 =s;
}
}
public void stop(){
go = false;
}
}
Файл RunningString html
Листинг 14.4. Файл RunningString.html
<html>
<headxtitle>
Applet</title>
</head>
<body>
Здесь работает апплет.<br>
<applet code = "RunningString.class" width = "1" height = "1">
</applet>
</body>
</html>
К сожалению, нет строгого стандарта на выполнение апплетов, и браузеры могут запускать их по-разному. Программа appietviewer способна показать апплет не так, как браузеры. Приходится проверять апплеты на всех имеющихся в распоряжении браузерах, добиваясь одинакового выполнения.
Приведем более сложный пример. Апплет showwindow создает окно somewindow типа Frame, в котором расположено поле ввода типа TextFieid. В него вводится текст, и после нажатия клавиши <Enter>
переносится в поле ввода апплета. В апплете присутствует кнопка. После щелчка кнопкой мыши по ней окно somewindow то скрывается с экрана, то вновь появляется на нем. То же самое должно происходить при уходе и появлении апплета в окне браузера в результате прокрутки, как записано в методах stop о и start о, но будет ли? Программа приведена в листингах 14.5 и 14.6, результат — на Рисунок 14.3.
Апплет создающий окно
Листинг 14.5. Апплет, создающий окно
// Файл ShowWindow.java
import j ava.awt.*;
import j ava.awt.event.*;
import java.applet.*;
public class ShowWindow extends Applet{
private SomeWindow sw = new SomeWindow();
private TextField tf = new TextField(30);
private Button b = new Button("Скрыть");
public void init(){
add(tf);
add(b);
sw.pack();
b.addActionListener(new ActShow());
sw.tf.addActionListener(new ActShow());
}
public void start(){ sw.setVisible(true);
}
public void stop(){ sw.setVisible(false);
}
public void destroy(){
sw.disposeO ; sw = tf = b = null;
}
public class ActShow implements ActionListener{
public void actionPerformed(ActionEvent ae){
if (ae.getSource() = sw.tf)
tf .setText(sw.tf .getText() ) ;
else if (b.getActionCoiranand() == "Показать"){
sw.setVisible(true);
b.setLabel("Скрыть") ; }
else{
sw.setVisible(false);
b.setLabel("Показать");
}
}
}
}
class SomeWindow extends Frame{
public TextField tf = new TextField(50);
SomeWindow(){
super(" Окно ввода");
add(new Label("Введите, пожалуйста, свое имя"), "North");
add(tf, "Center");
}
}
Файл ShowWindow html
Листинг 14.6. Файл ShowWindow.html
<html>
<headxtitle>
ShowWindow Applet</title>
</head>
<body>
Здесь появится Ваше имя.<br>
<applet code = "ShowWindow.class" width = "400" height = "50">
</applet>
</body>
</html>
Параметры для передачи в апплет
Листинг 14.7. Параметры для передачи в апплет
<html>
<head>
<title>
Applet</title>
</head>
<body>
Ниже выполняется апплет.<br>
<applet code = "HelloWorld.class" width = "400" height = "50">
<param name = "fontName" value = "Serif">
<param name = "fontStyle" value = "2">
<param name = "fontsize" value = "30">
</applet>
</body>
</html>
В апплете для приема каждого параметра надо воспользоваться методом getParameter (String name) класса Applet, Возвращающим строку типа String. В качестве аргумента этого метода задается значение параметра name в виде строки, причем здесь не различается регистр букв, а метод возвращает, значение параметра value тоже в виде строки.
Замечание
Замечание
Операторы System.out.println(), обычно записываемые в апплет для отладки, выводят указанные в них аргументы в специальное окно браузера Java Console. Сначала надо установить возможность показа этого окна. В Internet Explorer это делается установкой флажка Java Console enabled выбором команды Tools | Internet Options | Advanced. После перезапуска IE в меню View появляется команда Java Console.
В листинге 14.8 показан переработанный апплет HelloWorld. В нем назначен белый фон, а шрифт устанавливается с параметрами, извлеченными из HTML-файла.
Апплет принимающий параметры
Листинг 14.8. Апплет, принимающий параметры
import j ava.awt.*;
import j ava.applet.*;
public class HelloWorld extends Applet{ public void init(){
setBackground(Color.white);
String font = "Serif";
int style = Font.PLAIN, size = 10;
font = getParameter("fontName");
style = Integer.parselnt(getParameter("fontStyle"));
size = Integer.parselnt(getParameter("fontsize"));
setFont(new Font(font, style, size));
}
public void paint(Graphics g){
g.drawstring("Hello, XXI century World!", 10, 30);
}
}
Совет
Надеясь на то, что параметры будут заданы в HTML-файле, все-таки присвойте начальные значения переменным в апплете, как это сделано в листинге 14.8.
На Рисунок 14.4 показан работающий апплет.
Звук и изображение в апплете
Листинг 14.9, Звук и изображение в апплете
i mport java.applet.*;
import j ava.awt.*;
import java.awt.image.*;
public class SimpleAudioImage extends Applet{
private Image img;
private Audioclip ac;
public void init(){
img = getImage(getDocumentBase(), "javalogo52x88.gif");
ac = getAudioClip(getDocumentBase(), "yesterday.au");
}
public void start (){ ac.loop();
}
public void paint(Graphics g){
int w = img.getWidthfthis), h = img.getHeight(this);
g.drawlmage(img, 0, 0, 2 * w, 2 * h, this);
}
public void stop() { ac.stop();
}
}
Параметры тега <applet>
Параметры тега <applet>
Перечислим все параметры тега <appiet>.
Обязательные параметры:
code — URL-адрес файла с классом апплета или архивного файла; width и height — ширина и высота апплета в пикселах.Необязательные параметры:
codebase — URL-адрес каталога, в котором расположен файл класса апплета. Если этот параметр отсутствует, браузер будет искать файл в том же каталоге, где размещен соответствующий HTML-файл; archive — файлы всех классов, составляющих апплет, могут быть упакованы архиватором ZIP или специальным архиватором JAR в один или несколько архивных файлов. Параметр задает URL-адреса этих файлов через запятую; align — выравнивание апплета в окне браузера. Этот параметр имеет одно из следующих значений: ABSBOTTOM, ABSMIDDLE, BASELINE, BOTTOM, CENTER, LEFT, MIDDLE, RIGHT, TEXTTOP, TOP; hspace и vspace — горизонтальные и вертикальные поля, отделяющие апплет от других объектов в окне браузера в пикселах; download — задает порядок загрузки изображений апплетом. Имена изображений перечисляются через запятую в порядке загрузки; name — имя апплета. Параметр нужен, если загружаются несколько ап-плетов с одинаковыми значениями code и codebase ; style — информация о стиле CSS (Cascading Style Sheet); title — текст, отображаемый в процессе выполнения апплета; alt — текст, выводимый вместо апплета, если браузер не может загрузить его; mayscript — не имеет значения. Это слово указывает на то, что апплет будет обращаться к тексту JavaScript.Между тегами <applet> и </applet> можно написать текст, который будет выведен, если браузер не сможет понять тег <applet>. Вот полный пример:
<applet name = "AnApplet" code = "AnApplet.class"
archive = "anapplet.zip, myclasses.zip"
codebase = " http://www.some.com/public/applets "
width = "300" height = "200" align = "TOP"
vspace = "5" hspace = "5" mayscript
alt = "If you have a Java-enabled browser,
you would see an applet here.">
<hr>If your browser recognized the applet tag, «
you would see an applet here.<hr>
</applet>
Совет
Обязательно упаковывайте все классы апплета в zip- и гаг-архивы и указывайте их в параметре archive в HTML-файле. Это значительно ускорит загрузку апплета.
Следует еще сказать, что, начиная с версии HTML 4.0, есть тег <object>, предназначенный для загрузки и апплетов, и других объектов, например, ActiveX. Кроме того, некоторые браузеры могут использовать для загрузки апплетов тег <embed>.
Мы уже упоминали, что при загрузке апплета браузер создает контекст, в котором собирает все сведения, необходимые для выполнения апплета. Некоторые сведения из контекста можно передать в апплет.
Передача параметров
Передача параметров
Передача параметров в апплет производится с помощью тегов <param>, располагаемых между открывающим тегом <appiet> и закрывающим тегом </appiet> в HTML-файле. В тегах <param> указывается название параметра name и его значение value.
Передадим, например, в наш апплет Heiioworid параметры шрифта. В листинге 14.7 показан измененный файл HelloWorld.html.
Слежение за процессом загрузки
Слежение за процессом загрузки
Если вы хотя бы раз видели, как изображение загружается из Internet, то заметили, что оно появляется на экране по частям по мере загрузки. Это происходит в том случае, когда системное свойство awt.image. incrementalDraw имеет значение true.
При поступлении каждой порции изображения браузер вызывает логический метод imageUpdate () интерфейса ImageObserver. Аргументы этого метода содержат информацию о процессе загрузки изображения img. Рассмотрим их:
imageUpdate(Image img, int status, int x, int y, int width, int height);
Аргумент status содержит информацию о загрузке в виде одного целого числа, которое можно сравить со следующими константами интерфейса ImageObserver:
WIDTH — ширина уже загруженной части изображения известна, и может быть получена из аргумента width; HEIGHT — высота уже загруженной части изображения известна, и может быть получена из аргумента height;' PROPERTIES — свойства изображения уже известны, их можно получить методом getProperties{) класса Image; SOMEBITS — получены пикселы, достаточные для рисования масштабированной версии изображения; аргументы x, y, width, height определены; FRAMEBITS — получен следующий кадр изображения, содержащего несколько кадров; аргументы x, y, width, height не определены; ALLBITS — все изображение получено, аргументы x, y, width, height не содержат информации; ERROR — загрузка прекращена, рисование прервано, определен бит ABORT ; ABORT — загрузка прервана, рисование приостановлено до прихода следующей порции изображения.Вы можете переопределить этот метод в своем апплете и использовать его аргументы для слежения за процессом загрузки и определения момента полной загрузки.
Другой способ отследить окончание загрузки — воспользоваться методами класса MediaTracker. Они позволяют проверить, не окончена ли загрузка, или приостановить работу апплета до окончания загрузки. Один экземпляр класса MediaTracker может следить за загрузкой нескольких зарегистрированных в нем изображений.
Сведения об окружении апплета
Сведения об окружении апплета
Метод getCodeBase () возвращает URL-адрес каталога, в котором лежит файл класса апплета.
Метод getoocumentBase () возвращает URL-адрес каталога, в котором лежит HTML-файл, вызвавший апплет.
Браузер реализует интерфейс Appletcontext, находящийся в пакете java.applet. Апплет может получить ссылку на этот интерфейс методом getAppletContext().
С помощью методов getApplet (String name) и getApplets() интерфейса Appletcontext можно получить ссылку на указанный аргументом name апплет или на все апплеты, загруженные в браузер.
Метод showDocument(URL address) загружает в браузер HTML-файл с адреса address.
Метод showDocument (URL address, String target) загружает файл во фрейм, указанный вторым аргументом target. Этот аргумент может принимать следующие значения:
_seif — то же окно и тот же фрейм, в котором работает апплет; _parent — родительский фрейм апплета; _top — фрейм верхнего уровня окна апплета; _biank — новое окно верхнего уровня; name — фрейм или окно с именем name , если оно не существует, то будет создано.Вывод изображения
Рисунок 14.5. Вывод изображения
Перед выводом на экран изображение можно преобразовать, но об этом поговорим в следующей главе.
Как видите, апплету в браузере позволено очень немного. Это не случайно. Апплет, появившийся в браузере откуда-то из Internet, может натворить много бед. Он может быть вызван из файла с увлекательным текстом, невидимо обыскать файловую систему и похитить секретные сведения, или, напротив, открыть окно, неотличимое от окна, в которое вы вводите пароль, и перехватить его.
Поэтому браузер сообщает при загрузке апплета: "Applet started", а в строке состояния окна, открытого апплетом, появляется надпись: "Warning: Applet Window".
Но это не единственная защита от апплета. Рассмотрим данную проблему подробнее.
Апплеты были первоначальным практическим применением
Заключение
Апплеты были первоначальным практическим применением Java. За первые два года существования Java были написаны тысячи очень интересных и красивых апплетов, ожививших WWW. Масса апплетов разбросана по Internet, хорошие примеры апплетов собраны в JDK в каталоге demo\applets.
В JDK вошел целый пакет java.applet, в который фирма SUN собиралась заносить классы, развивающие и улучшающие апплеты.
С увеличением скорости и улучшением качества компьютерных сетей значение апплетов сильно упало. Теперь вся обработка данных, прежде выполняемая апплетами, переносится на сервер, браузер только загружает и показывает результаты этой обработки, становится "тонким клиентом".
С другой стороны, появилось много специализированных программ, в том числе написанных на Java, загружающих информацию из Internet. Такая возможность есть сейчас у всех музыкальных и видеопроигрывателей.
Фирма SUN больше не развивает пакет java.applet. В нем так и остался один класс и три интерфейса. В библиотеку Swing вошел класс JApplet, расширяющий класс Applet. В нем есть дополнительные возможности, например, можно установить систему меню. Он способен использовать все классы библиотеки Swing. Но большинство браузеров еще не имеют Swing в своем составе, поэтому приходится загружать классы Swing с сервера или включать их в jar-архив вместе с классами апплета.
Защита от апплета
Защита от апплета
Браузер может вообще отказаться от загрузки апплетов. В Netscape Communicator это делается с помощью флажка Enable Java в окне, вызываемом командой Edit | Preferences | Advanced, в Internet Explorer — в окне после выбора команды Tools | Internet Options | Security. В таком случае говорить в этой книге больше не о чем.
Если браузер загружает апплет, то создает ему ограничения, так называемую "песочницу" (sandbox), в которой резвится апплет, но выйти из которой не может. Каждый браузер создает свои ограничения, но обычно они заключаются в том, что апплет:
не может обращаться к файловой системе машины, на которой он выполняется, даже для чтения файлов или просмотра каталогов; может связаться по сети только с тем сайтом, с которого он был загружен; не может прочитать системные свойства, как это делает, например, приложение в листинге 6.4; не может печатать на принтере, подключенном к тому компьютеру, на котором он выполняется; не может воспользоваться буфером обмена (clipboard); не может запустить приложение методом ехес (); не может использовать "родные" методы или загрузить библиотеку методом load (); не может остановить JVM методом exit (); не может создавать классы в пакетах java.*, а классы пакетов sun.* не может даже загружать.Браузеры могут усилить или ослабить эти ограничения, например, разрешить локальным апплетам, загруженным с той же машины, где они выполняются, доступ к файловой системе. Наименьшие ограничения имеют доверенные (trusted) апплеты, снабженные электронной подписью с помощью Классов ИЗ пакетов java.security.*.
При создании приложения, загружающего апплеты, необходимо обеспечить средства проверки апплета и задать ограничения. Их предоставляет класс securityManager. Экземпляр этого класса или его наследника устанавливается в JVM при запуске виртуальной машины статическим методом setSecurityManager(SecurityManager sm) класса System. Обычные приложения не могут использовать данный метод.
Каждый браузер расширяет класс SecurityManager по-своему, устанавливая те или иные ограничения. Единственный экземпляр этого класса создается при запуске JVM в браузере и не может быть изменен.