Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Растровые изображения в аплете

Растровые изображения в автономном приложении
Класс MediaTracker
Класс ImageObserver
Создание изображений
Фильтр RGBImageFilter
Фильтр CropImageFilter
Полупрозрачные изображения
Класс PixelGrabber
Внеэкранное изображение

Назад Вперед

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).

pic1.gif (41772 bytes)

Рис. 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);    
} 

Назад Вперед

[Назад]