Немного Java - и страница ожила

         

Описание исходных текстов


Многие RAD-продукты для создания Java-приложений имеют в своем составе различные опции автоматизации разработки, и система Microsoft Visual J++, с помощью которой создавались все примеры, - не исключение. Она может автоматически генерировать заготовку исходного текста Java-приложения, затем ее можно дополнить в соответствии с задачами, решаемыми приложением. В соответствующей диалоговой панели можно указать, что необходимо подготовить исходные тексты многопоточного аплета.

Созданный таким образом аплет использует способ реализации многопоточности, основанный на применении интерфейса Runnable:

public class SimpleScroll extends Applet implements Runnable { private Thread m_SimpleScroll = null; . . . }

В классе SimpleScroll определено поле m_SimpleScroll класса Thread, хранящее ссылку на поток, запускаемый нашим аплетом для периодической перерисовки своего окна. Это поле инициализируется значением null, что необходимо для правильной работы аплета. В поле m_Text типа String хранится текстовая строка, которая передается аплету в документе HTML с помощью специального параметра. Установив дополнительные параметры, можно передавать цвет, стиль и размер шрифта для отображения текстовой строки. Аплет определяет длину строки и записывает ее в поле m_StringSize. Текущая позиция начала отображения строки при вызове метода paint хранится в поле m_CurrentXPosition. Эта позиция периодически уменьшается на один пиксел при каждом вызове метода paint.

Рассмотрим теперь самые важные методы нашего аплета. Метод init получает управление при инициализации аплета. Прежде всего он получает из документа HTML значение единственного параметра - текстовую строку, которая будет сдвигаться в окне аплета. Параметр извлекается с помощью метода getParameter и сохраняется в поле m_Text. Далее метод init определяет размерности текущего шрифта, выбранного для показа строки, вызывая для этого метод getFontMetrics. В качестве параметра ему передается значение, возвращенное методом getFont. Метрики сохраняются в поле fm. Пользуясь этими метриками, метод init определяет длину строки m_Text с помощью метода stringWidth. После определения длины строки инициализируется поле m_CurrentXPosition, хранящее текущую позицию для рисования сдвигаемой строки. В это поле записывается координата правой границы окна аплета. Ширина окна аплета определяется с помощью метода size. Последнее, что делает метод init, - устанавливает желтый (в нашем случае) цвет для фона окна аплета.


Следующий метод - paint - рисует периодически сдвигаемую текстовую строку в текущей позиции m_CurrentXPosition:
g.drawString(m_Text, m_CurrentXPosition, 20);
Затем эта позиция уменьшается на единицу, в результате чего при следующем вызове метода paint строка будет нарисована левее на один пиксел:
m_CurrentXPosition-;
Когда вся строка будет сдвинута влево и исчезнет с экрана, текущая позиция устанавливается равной ширине окна аплета:
if(m_CurrentXPosition < -m_StringSize) m_CurrentXPosition = size().width;
Далее строка снова появится в правой части окна и будет сдвигаться влево при каждом вызове метода paint.
Метод start получает управление при активизации, когда в окне браузера появляется документ HTML с нашим аплетом. Если в поле m_SimpleScroll находится значение null, метод start создает новый поток, который будет периодически перерисовывать окно аплета:
if (m_SimpleScroll == null) { m_SimpleScroll = new Thread(this); m_SimpleScroll.start(); }
Здесь новый поток класса Thread получает при создании ссылку на аплет. Новый поток не будет работать автоматически. Для того чтобы его запустить, мы вызываем метод start из класса Thread.
Когда пользователь покидает страницу с аплетом, следует остановить работу потока, чтобы он не отнимал системные ресурсы. Наша реализация метода stop делает это, вызывая метод stop из класса Thread:
if (m_SimpleScroll != null) { m_SimpleScroll.stop(); m_SimpleScroll = null; }
Разумеется, остановка выполняется только в том случае, если поток был создан. Это можно узнать по значению поля m_SimpleScroll, в котором должна находиться правильная ссылка на объект. После остановки потока мы записываем в это поле значение null.
Метод run, как мы уже говорили, не вызывается никаким другим методом, определенным в нашем аплете. Этот метод получает управление и работает в рамках самостоятельного потока, когда для соответствующего объекта вызывается метод start. Это происходит при активизации аплета. Run включает в себя бесконечный цикл, внутри которого вызывается метод repaint, с последующей задержкой на 50 мс:
try { repaint(); Thread.sleep(50); } catch (InterruptedException e) { stop(); }
При возникновении исключения InterruptedException поток останавливается методом stop.
Продолжение в следующем номере.
Александр Вячеславович Фролов, Григорий Вячеславович Фролов - авторы серий книг "Библиотека системного программиста" и "Персональный компьютер. Шаг за шагом".
E-mail: frolov@glas.apc.org
Web: http://www.glasnet.ru/~frolov, http://www.dials.ccas.ru/frolov

Содержание раздела