Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
89
Добавлен:
24.02.2016
Размер:
202.75 Кб
Скачать

Применение анимации для мультизадачности

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

Работа апплетов основана на обработке событий. Основной (первичный) класс апплета обрабатывает события, переопределяя те или иные методы суперкласса Applet.

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

Перерисовка окна апплета выполняется методом paint(), который вызывается виртуальной машиной Java асинхронно по отношению к выполнению другого кода апплета, если содержимое окна было перекрыто другими окнами.

Возникает вопрос, а можно ли воспользоваться методом paint() для периодической перерисовки окна апплета, организовав в нем, например, бесконечный цикл с задержкой. К сожалению, так поступать нельзя. Метод paint() после перерисовки апплета должен сразу возвратить управление, иначе работа апплета будет заблокирована.

Единственный выход из создавшейся ситуации - создание потока (или нескольких потоков), которые будут выполнять рисование в окне апплета асинхронно по отношению к коду апплета. Например, можно создать поток, который периодически обновляет окно апплета, вызывая для этого метод repaint(), или рисовать из потока непосредственно в окне апплета (в апплете MultiTask использовался именно этот способ).

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

Идея заключается в том, что основной класс апплета DoubleTask (пример 2), который является дочерним по отношению к классу Applet, дополнительно реализует интерфейс Runnable, переопределяя метод run() этого интерфейса:

Пример 2. Файл DoubleTask.java -

import java.applet.*;

import java.awt.*;

public class DoubleTask extends Applet implements Runnable

{ public DoubleTask()

{ // здесь можно добавить код конструктора

}

public void init()

{ resize(320, 240); // установка размера апплета

// здесь можно добавить код инициализации апплета

}

public void destroy()

{ // здесь можно добавить код завершения работы апплета

}

public void paint(Graphics g)

{ // здесь можно добавить код вывода в окно апплета

}

public void start()

{ // создание и запуск потока

if(task==null) { task=new Thread(this); task.start(); }

}

public void stop()

{ // остановка потока

if(task!=null) task.stop();

}

public void run()

{ // здесь можно добавить код, который будет

// выполняться в рамках отдельного потока

}

Thread task=null; // ссылка на поток

// здесь можно добавить специализированный для класса код

}

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

Для создание потока используется оператор new. Поток создается как объект класса Thread, причем конструктору передается ссылка на класс апплета:

task=new Thread(this);

Запуск потока осуществляется методом start для объекта task. При запуске потока начинает работать метод run(), определенный в классе апплета. Причем одновременно с этим код методов апплета также выполняется, так что апплет может обрабатывать различные события в методах обработки событий.

Определим, например, метод paint() апплета следующим образом:

public void paint(Graphics g)

{ g.drawString("Random value "+Math.random(),10,20);

}

А в методе run() реализуем бесконечный цикл, в котором периодически с задержкой 50 миллисекунд вызывается метод repaint(), вызывающий перерисовку апплета:

public void run()

{ while(true)

{

repaint();

try{ Thread.sleep(50); } catch(InterruptedException e) { stop(); }

}

}

Для выполнения задержки метод run() вызывает sleep() класса Thread. Этот метод может вызвать исключение InterruptedException, которое можно обработать с помощью операторов try и catch. В данном случае при возникновении исключения апплет прекращает свою работу.

Такая перерисовка может вызвать мигание окна апплета, поэтому удачной ее назвать нельзя, но этот апплет можно использовать просто как пример реализации “двухзадачности” для апплета.