Назад
Вперед
9.3. Класс MediaTracker
Пример показывает применение класса MediaTracker для
синхронизации загрузки набора кадров
анимационного изображения. Этот класс позволяет
дождаться завершения загрузки всех кадров перед
тем как запускать анимацию.
Исходный текст примера
Архив проекта для Java WorkShop 2.0
Демонстрация
(ваш браузер должен уметь работать с аплетами
Java JDK 1.1)
Немного теории
Как мы говорили в описании первого примере
этого раздела нашей библиотеки, при создании
ссылки на объект Image как в аплете, так и в
автономном приложении фактической загрузки
данных не происходит. Данные начинают
загружаться только тогда, когда программа
вызывает метод drawImage чтобы нарисовать растровое
изображение.
Но метод drawImage не дожидается завершения
процесса загрузки или рисования, а только
запускает процесс, сразу возвращая управление
вызывающей программе. Загрузка и рисование
выполняются в отдельном потоке асинхронно по
отношению к выполнению потока, вызвавшего метод
drawImage.
В некоторых случаях, однако, прежде чем
продолжить свою работу, программа должна
убедиться, что все необходимые изображения уже
загружены. В частности, перед началом анимации
следует загрузить все кадры анимационного
изображения.
Специально для прослеживания процесса
загрузки изображений в библиотеке классов Java
предусмотрен класс с именем MediaTracker.
Как им пользоваться для ожидания загрузки
изображений?
Мы рассмотрим здесь простейший способ,
пригодный, однако, для большинства случаев.
Прежде всего необходимо создать объект класса
MediaTracker с помощью соответствующего конструктора:
MediaTracker mt = new MediaTracker(this);
В качестве параметра конструктору следует
передать ссылку на компонент, в окне которого
будет рисоваться растровое изображение.
Далее вы должны добавить изображения в
созданный объект методом addImage:
Image img1, img2, img3, img4;
. . .
mt.addImage(img1, 0);
mt.addImage(img2, 0);
mt.addImage(img3, 0);
mt.addImage(img4, 0);
Через первый параметр мы передали методу addImage
ссылку на изображение, процесс загрузки которого
необходимо отслеживать, а через второй
идентификатор изображения.
В данном случае все добавленные изображения
имеют одинаковый идентификатор, так как мы не
будем прослеживать их загрузку по отдельности.
Но если для вас имеет значение порядок загрузки
изображений или вам нужно проследить загрузку
каких либо конкретных изображений из числа
добавленных в объект MediaTracker, следует задать для
каждого изображения свой идентификатор.
Теперь чтобы дождаться завершения загрузки
всех изображений мы вызываем метод waitForAll,
определенный в классе MediaTracker:
try
{
mt.waitForAll();
}
catch(InterruptedException ie)
{
. . .
}
При этом необходимо определить обработчик
исключения InterruptedException.
Описание примера
В нашем примере класс MediaTracker применяется для
ожидания загрузки трех кадров, последовательно
отображаемых в окне аплета (рис. 1).
Рис. 1. Кадры, отображаемые в окне аплета
Рассмотрим исходный текст аплета.
Главный класс MTrackerDemo
Главный класс аплета MTrackerDemo создан нами на базе
класса Applet и реализует интерфейс Runnable:
import java.applet.Applet;
import java.awt.*;
public class MTrackerDemo extends Applet
implements Runnable
{
. . .
}
Данный интерфейс нужен для организации
многопоточного режима работы.
Поток, ссылка на который хранится в поле thr,
занимается рисованием кадров:
Thread thr = null;
В поле bImagesLoaded мы храним признак завершения
загрузки кадров анимации:
boolean bImagesLoaded = false;
Номер текущего отображаемого кадра записан в
поле nCurrentImage:
int nCurrentImage = 0;
Массив im хранит изображения отдельных кадров:
Image[] im;
Методы start и stop класса MTrackerDemo
Когда пользователь загружает в окно браузера
документ HTML c аплетом, метод start запускает поток
анимации на выполнение:
public void start()
{
if(thr == null)
{
thr = new Thread(this);
thr.start();
}
}
Метод stop вызывается, если пользователь
покидает указанную страницу:
public void stop()
{
if(thr != null)
{
thr.stop();
thr = null;
}
}
В его задачу входит останов потока анимации.
Метод run класса MTrackerDemo
Этот метод работает в рамках отдельного потока.
Вначале он устанавливает начальный номер
текущего отображаемого кадра равным нулю:
nCurrentImage = 0;
Далее проверяется, были ли загружены все кадры:
if(!bImagesLoaded)
{
. . .
}
Если нет (как это бывает всегда при первом
запуске метода run) начинается процесс загрузки
отдельных кадров анимации.
Прежде всего мы создаем объект класса MediaTracker,
который необходим для ожидания загрузки всех
кадров:
MediaTracker mt = new MediaTracker(this);
Далее мы в цикле создаем для каждого кадра
объект класса Image (методом getImage) и затем добавляем
его в MediaTracker с применением метода addImage:
im = new Image[3];
String s;
for(int i = 0; i < 3; i++)
{
s = "img" + (i + 1) + ".jpg";
im[i] =
getImage(getDocumentBase(), s);
mt.addImage(im[i], 0);
}
Ожидание загрузки выполняется методом waitForAll:
try
{
mt.waitForAll();
bImagesLoaded = !mt.isErrorAny();
}
catch(InterruptedException ie)
{
stop();
}
Этот метод может вызвать появление исключения
InterruptedException, которое мы обрабатываем.
В качестве признака завершения загрузки мы
используем инвертированное значение, полученное
от метода isErrorAny. Если ожидание завершилось без
ошибок, этот метод возвращает значение false, а в
переменную bImagesLoaded (признак завершения загрузки)
записывается значение true.
После завершения загрузки всех трех
изображений мы получаем контекст отображения
для окна аплета, а затем начинаем анимацию:
Graphics g = getGraphics();
while(true)
{
if(bImagesLoaded)
{
g.drawImage(im[nCurrentImage],
0, 0, null);
nCurrentImage++;
if(nCurrentImage > 2)
nCurrentImage = 0;
}
try
{
thr.sleep(2000);
}
catch(InterruptedException ie)
{
stop();
}
}
}
Метод run в цикле рисует по очереди кадры
анимации методом drawImage, выполняя на каждой
итерации задержку в две секунды.
Метод paint класса MTrackerDemo
Если загрузка изображений не завершена, метод
paint выводит в окно аплета сообщение "Loading
images…":
public void paint(Graphics g)
{
if(!bImagesLoaded)
g.drawString("Loading images...",
10, 30);
}
Назад Вперед |