Текст книги "Java: руководство для начинающих (ЛП)"
Автор книги: Герберт Шилдт
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 30 (всего у книги 36 страниц)
Хотя рассмотренный ранее класс SimpleApplet представляет собой подлинный апплет, он все же не содержит всех тех элементов, которые требуются для большинства апплетов. Почти во всех апплетах, кроме самых простых, переопределяется ряд методов, с помощью которых браузер или другая программа просмотра апплетов может контролировать их выполнение. Срок действия апплета определяется методами init (), start(),stop() HdestroyO, которые относятся к классу Applet. Пятый метод, paint (), часто переопределяется в апплетах, создаваемых на основе AWT. Этот метод наследуется от класса Component из библиотеки AWT. Четыре упомянутых выше метода собраны вместе с методом paint () в приведенной ниже заготовке апплета. // Заготовка апплета, import java.awt.*; import java.applet.*; /* */ public class AppletSkel extends Applet { // Этот метод вызывается первым, public void init() { // инициализировать апплет } /* Этот метод вызывается вторым после метода init(). Он вызывается и в тех случаях, когда требуется возобновить работу апплета. */ public void start() { // запустить или возобновить выполнение апплета } // Этот метод вызывается для остановки работы апплета, public void stop() { // приостановить выполнение апплета } /* Этот метод вызывается последним для завершения работы апплета. */ public void destroy() { // выполнить действия, завершающие выполнение апплета. } /* Этот метод вызывается для обновления данных в окне апплета. */ public void paint(Graphics g) { // обновить содержимое окна апплета } }
Несмотря на то что код этой заготовки не выполняет никаких действий, его можно скомпилировать и запустить на выполнение, а в дальнейшем создавать на его основе настоящие апплеты.
На заметку Переопределять метод paint () приходится главным образом в апплетах, создаваемых на основе библиотеки AWT. А в апплетах, создаваемых на основе библиотеки Swing, для перерисовки содержимого окна апплета чаще всего используется другой механизм. Инициализация и завершение апплетов
Необходимо ясно представлять себе, в каком именно порядке вызываются методы, входящие в состав заготовки апплета. При запуске апплета на выполнение вызываются три метода в следующей последовательности.
Метод init().
Метод start().
Метод paint().
По завершении работы апплета вызываются следующие методы.
Метод stop().
Метод destroy().
Рассмотрим все эти методы более подробно.
Метод init () вызывается первым при запуске апплета на выполнение. В теле этого метода, как правило, инициализируются переменные и выполняются другие действия, связанные с подготовкой апплета к выполнению.
После метода init () вызывается метод start (). С его помощью выполнение апплета возобновляется после остановки. Обычно это происходит в тех случаях, когда пользователь возвращается к ранее посещавшейся веб-странице, содержащей апплет. Таким образом, в течение срока действия апплета метод start () может быть вызван несколько раз.
Метод paint () вызывается всякий раз, когда данные, выводимые апплетом, должны быть обновлены в его окне, как пояснялось ранее.
Когда пользователь покидает веб-страницу, содержащую апплет, вызывается метод stop (). Это может быть сделано для того, чтобы приостановить любые порожденные потоки, созданные в апплете, а также выполнить другие действия для благополучного перевода апплета в режим простоя. Не следует, однако, забывать, что вызов метода stop () совсем не означает завершение работы самого апплета. Когда пользователь вернется к веб-странице с апплетом, его выполнение будет возобновлено благодаря вызову метода start ().
Метод destroy () вызывается в том случае, когда апплет больше не нужен. Этот метод служит для выполнения операций по завершении работы апплета. Запрос на перерисовку окна апплета
Вывод данных в окне апплета происходит только в том случае, если исполняющая система вызывает метод paint (). В связи с этим возникает вопрос: можно ли по инициативе апплета произвести перерисовку окна? Необходимость в этом чаще всего возникает при изменении данных, предназначенных для отображения. Допустим, в апплете отображается движущееся рекламное сообщение. Какой механизм должен быть использован для обновления окна всякий раз, когда внешний вид сообщения должен измениться? Напомним, что одним из основных ограничений, налагаемых на апплет, является требование как можно быстрее возвращать управление исполняющей системе. Поэтому в методе paint () нельзя создать цикл, в котором постоянно изменялся бы вид сообщения. Принимая во внимание это ограничение, можно прийти к заключению, что вывод данных в окне апплета – дело непростое. К счастью, это совсем не так. Если требуется изменить данные, отображаемые в окне апплета, достаточно вызвать метод repaint ().
Этот метод определен в классе Component, входящем в состав библиотеки AWT. Он сообщает исполняющей системе о том, что метод paint () должен быть вызван из апплета при первой же возможности. Если, например, в апплете возникнет потребность вывести данные, их нужно сначала сохранить, а затем вызвать метод repaint (). В итоге будет вызван метод paint (), чтобы отобразить сохраненные изменившиеся данные. Так, если в апплете требуется вывести символьную строку, ее нужно сначала сохранить в переменной типа String, а затем вызвать метод repaint (). А в самом методе paint () символьная строка будет выведена с помощью метода drawstring ().
Ниже приведена простейшая форма вызова метода repaint (). void repaint()
Этот метод производит перерисовку всего окна апплета.
В другой форме вызова метода repaint () задается конкретная область для перерисовки. void repaint(int слева, int сверху, int ширина, int высота)
Координаты верхнего левого угла перерисовываемой области задаются с помощью параметров слева и сверху, а параметры ширина и высота определяют конкретную ширину и высоту этой области. Все размеры задаются в пикселях. Указывая области для перерисовки, можно значительно увеличить быстродействие программы, поскольку для обновления содержимого окна требуется немало времени. Если же требуется перерисовать лишь небольшую область, то задавать обновление всего окна нет никакой надобности.
Применение метода repaint () будет продемонстрировано в примере для опробования 14.1. Метод update ()
Перерисовку окна апплета можно организовать и с помощью метода update (), который переопределяется во многих апплетах. Этот метод объявляется в классе Component и вызывается в том случае, если требуется перерисовать часть окна апплета. В используемом по умолчанию варианте метода update () просто вызывается метод paint (). Но, переопределив метод update (), можно выполнить и более сложные операции, рассмотрение которых, впрочем, выходит за рамки этой книги. Переопределение метода update () осуществляется только в апплетах, создаваемых на основе библиотеки AWT.
Пример для опробования 14.1. Простой апплет для формирования крупного заголовка на веб-странице
Работу метода repaint () удобно продемонстрировать на примере следующего простого апплета. Он выполняет прокрутку крупного заголовка в окне слева направо. А поскольку такую прокрутку нужно выполнять постоянно, то реализовать ее следует в отдельном потоке, который создается при инициализации апплета. Подобные крупные заголовки называются еще баннерами и часто встречаются на веб-страницах, а в этом проекте демонстрируется, каким образом можно создать такой заголовок, используя апплет Java.
Последовательность действий
Создайте файл Banner.java.
Начните создание апплета со следующих строк кода: /* Пример для опробования 14.1. Простой апплет, отображающий крупный заголовок. В этом апплете создается поток, управляющий прокруткой крупного заголовка, хранящегося в переменной msg, справа налево в окне апплета. */ import java.awt.*; import java.applet.*; /* */ public class Banner extends Applet implements Runnable { String msg = " Java Rules the Web "; // "Java правит Паутиной" Thread t; boolean stopFlag; // инициализировать переменную t пустым значением null public void init() { t = null; } }
Обратите внимание на то, что класс Banner не только является подклассом, производным от класса Applet, но и реализует интерфейс Runnable. Это необходимо потому, что апплет создает еще один поток исполнения, который служит для прокрутки крупного заголовка по горизонтали. Текст крупного заголовка хранится в переменной msg типа String, ссылка на поток, в котором выполняется апплет, хранится в переменной t, а логическая переменная stopFlag служит для остановки апплета. В методе init () переменной t исходно присваивается пустое значение null.
Введите метод start (), исходный код которого приведен ниже. // запустить поток public void start() { t = new Thread(this); stopFlag = false; t.start(); } Исполняющая система вызывает метод start () для запуска апплета на выполнение. В этом методе создается новый поток исполнения, а ссылка на него присваивается переменной t типа Thread. Затем переменная stopFlag инициализируется логическим значением false. Далее поток запускается при вызове t. start (). Это, в свою очередь, приводит к вызову метода run (). Следует, однако, иметь ввиду, что метод start () из класса Thread не имеет ничего общего с одноименным методом, определенным в классе Applet.
Введите метод run (), исходный код которого приведен ниже. // Точка входа в поток, манипулирующий крупным заголовком, public void run () { // отобразить крупный заголовок снова for( ; ; ) { try { repaint (); Thread.sleep(250); if(stopFlag) break; } catch(InterruptedException exc) {} } } В методе run () вызывается метод repaint (), что в конечном итоге приводит к вызову метода paint () и отображению текущего содержимого переменной msg на экране. Между последовательными шагами цикла выполнение метода run () приостанавливается на четверть секунды. В результате содержимое переменной msg постоянно прокручивается справа налево. На каждом шаге цикла проверяется содержимое переменной stopFlag. И как только она примет логическое значение true, выполнение метода run () завершится.
Введите методы stop () и paint (), исходный код которых приведен ниже. // остановить выполнение апплета public void stop() { stopFlag = true; t = null; } // отобразить крупный заголовок public void paint(Graphics g) { char ch; ch = msg.charAt(0); msg = msg.substring(1, msg.length()); msg += ch; g.drawstring(msg, 50, 30); }
Если пользователь браузера переходит на другую веб-страницу, вызывается метод stop (), в котором переменной stopFlag присваивается логическое значение true, завершая тем самым выполнение метода run (). В этом же методе переменной t присваивается пустое значение null. После этого она уже не ссылается на объект типа Thread, а следовательно, этот объект будет удален системой “сборки мусора”. Этот механизм используется для остановки потока, когда страница с апплетом не просматривается. Когда же она снова появляется в окне браузера, вызывается метод start (), запускающий новый поток манипулирования крупным заголовком.
В методе paint () символы строки крупного заголовка, хранящегося в переменной msg, постоянно сдвигаются влево. После каждого сдвига вызывается метод drawstring (), выводящий текущее содержимое переменной msg на экран.
Ниже приведен весь исходный код апплета для формирования крупного заголовка на веб-странице. /* Пример для опробования 14.1. Простой апплет, отображающий крупный заголовок. В этом апплете создается поток, управляющий прокруткой крупного заголовка, хранящегося в переменной msg, справа налево в окне апплета. */ import java.awt.*; import java.applet.*; /* */ public class Banner extends Applet implements Runnable { String msg = " Java Rules the Web "; // "Java правит Паутиной" Thread t; boolean stopFlag; // инициализировать переменную t пустым значением null public void init() { t = null; } // запустить поток public void start() { t = new Thread(this) ; stopFlag = false; t.start(); } // Точка входа в поток, манипулирующий крупным заголовком, public void run() { // отобразить крупный заголовок снова for( ; ; ) { try { repaint (); Thread.sleep(250); if(stopFlag) break; } catch(InterruptedException exc) {} } } // остановить выполнение апплета public void stop() { stopFlag = true; t = null; } // отобразить крупный заголовок public void paint(Graphics g) { char ch; ch = msg.charAt(0) ; msg = msg.substring(1, msg.length()); msg += ch; g.drawstring(msg, 50, 30); } }
Ниже приведен результат выполнения данного апплета. Применение строки состояния
Помимо отображения информации в основном окне, апплет может также выводить сообщения в строке состояния браузера или другого средства просмотра апплетов. Для вывода сообщения в строке состояния следует вызвать метод showStatus (), определенный в классе Applet. При вызове этому методу в качестве параметра передается выводимая символьная строка. Ниже приведена общая форма объявления метода showStatus(). void showStatus(String сообщение)
где сообщение обозначает выводимую символьную строку.
В строке состояния удобно отображать сведения о том, что происходит при выполнении апплета, подсказывать пользователю дальнейшие действия или выводить сообщения об ошибках. Строка состояния незаменима при отладке, поскольку дает возможность без труда выводить всю необходимую информацию об апплете.
Ниже приведен пример апплета, демонстрирующий применение метода showStatus(). // Использование строки состояния, import java.awt.*; import java.applet.*; /* */ public class StatusWindow extends Applet{ // отобразить содержимое переменной msg в окне апплета public void paint(Graphics g) { g.drawString("This is in the applet window.", 10, 20); showStatus("This is shown in the status window."); } }
Выполнение этого апплета дает приведенный ниже результат.
Передача параметров апплету
По мере необходимости апплету можно передать один или более параметр. Для этой цели предусмотрен атрибут PARAM дескриптора APPLET. С его помощью задается имя и значение параметра. А для извлечения параметра служит метод getParameter (), определенный в классе Applet. Он объявляется следующим образом: String getParameter(String имя_параметра)
где имя_параметра обозначает конкретное имя передаваемого параметра. Этот метод возвращает значение указанного параметра в виде объекта типа String. Так, если апплету требуется передать числовое или логическое значение, его строковое представление придется преобразовать во внутренний формат. Если же указанный параметр не найден, метод возвращает пустое значение null. Поэтому в исходный код апплетов следует включать проверку правильности значений, возвращаемых методом getParameter (). Желательно также проверять, правильно ли было выполнено преобразование числового значения параметра, передаваемого апплету.
Ниже приведен пример, демонстрирующий процесс передачи параметров апплету. // Передача параметров апплету, import java.awt.*; import java.applet.*; // Параметры передаются апплету в коде HTML. /*