Оглавление

Растровые изображения
Загрузка и рисование
Класс Image
Ожидание загрузки
Видео
Аплет CDRotation

    Аплет CDRotation

    В этом разделе мы расскажем об аплете CDRotation, в окне которого вращается компакт-диск.

    В левом верхнем углу каждого кадра отображается его порядковый номер (рис. 1). Этот номер не нарисован в файлах кадров, а надписывается приложением после рисования очередного кадра. Такое невозможно, если располагать в документе HTML файл AVI или многосекционный файл GIF.

    pic01.gif (3268 bytes)

    Рис. 1. Изображение вращающегося компакт-диска в окне аплета CDRotation

    Исходные тексты приложения

    Главный файл исходных текстов приложения CDRotation представлен в листинге 1.

    Листинг 1. Файл CDRotation.java

    import java.applet.*;
    
    import java.awt.*;
    public class CDRotation extends Applet
    
      implements Runnable
    
    {
    
      Thread m_CDRotation = null;
    
      private Graphics m_Graphics;
    
      private Image m_Images[];
    
      private int m_nCurrImage;
    
      private int m_nImgWidth  = 0;
    
      private int m_nImgHeight = 0;
    
      private boolean m_fAllLoaded = false;
    
      private final int NUM_IMAGES = 11;
      public String getAppletInfo()
    
      {
    
        return "Name: CDRotation";
    
      }
      private void displayImage(Graphics g)
    
      {
    
        if (!m_fAllLoaded)
    
          return;
        g.drawImage(m_Images[m_nCurrImage],
    
           (size().width - m_nImgWidth)   / 2,
    
           (size().height - m_nImgHeight) / 2,
    
            null);
        g.drawString(
    
          (new Integer(m_nCurrImage)).toString(),
    
          (size().width - m_nImgWidth)  /2,
    
         ((size().height - m_nImgHeight)/2)+
    
         10);
    
      }
      public void paint(Graphics g)
    
      {
    
        Dimension dimAppWndDimension = size();
    
        g.setColor(Color.white);
    
        g.fillRect(0, 0, 
    
          dimAppWndDimension.width  - 1, 
    
          dimAppWndDimension.height - 1);
    
        g.setColor(Color.black);
    
        g.drawRect(0, 0, 
    
          dimAppWndDimension.width  - 1, 
    
          dimAppWndDimension.height - 1);
        if (m_fAllLoaded)
    
        {
    
          displayImage(g);
    
        }		
        else
    
          g.drawString("Please, wait...", 
    
            10, dimAppWndDimension.height / 2);
    
      }
      public void start()
    
      {
    
        if (m_CDRotation == null)
    
        {
    
          m_CDRotation = new Thread(this);
    
          m_CDRotation.start();
    
        }
    
      }	
      public void stop()
    
      {
    
        if (m_CDRotation != null)
    
        {
    
          m_CDRotation.stop();
    
          m_CDRotation = null;
    
        }
    
      }
      public void run()
    
      {
    
        m_nCurrImage = 0;
        if (!m_fAllLoaded)
    
        {
    
          repaint();
    
          m_Graphics = getGraphics();
          m_Images   = new Image[NUM_IMAGES];
          MediaTracker tracker =
    
             new MediaTracker(this);
          String strImage;
          for (int i = 0; i < NUM_IMAGES; i++)
    
          {
    
            strImage = "images/cdimg0" + 
    
              ((i < 10) ? "0" : "") + i + ".gif";
            m_Images[i] = getImage(
    
              getDocumentBase(), strImage);
            tracker.addImage(m_Images[i], 0);
    
          }
          try
    
          {
    
    	tracker.waitForAll();
    	m_fAllLoaded = !tracker.isErrorAny();
    
          }
    
          catch (InterruptedException e)
    
          {
    
          }	
          if (!m_fAllLoaded)
    
          {
    
            stop();
    
            m_Graphics.drawString(
    
              "Load error", 10,
    
               size().height / 2);			  
            return;
    
          }
          m_nImgWidth  = 
    
            m_Images[0].getWidth(this);
    
          m_nImgHeight =
    
             m_Images[0].getHeight(this);
    
        }	
        repaint();
        while (true)
    
        {
    
          try
    
          {
    
            displayImage(m_Graphics);
    
    	m_nCurrImage++;
    	if(m_nCurrImage == NUM_IMAGES)
    
    	m_nCurrImage = 0;
            Thread.sleep(30);
    
          }
          catch (InterruptedException e)
    
          {
    
    	stop();
    
          }
    
        }
    
      }
    
    }

    Листинг 2 содержит исходный текст документа HTML, созданного для аплета CDRotation.

    Листинг 2. Файл CDRotation.tmp.html

    <applet name="CDRotation"
    
      code="CDRotation" 
    
      codebase=
    
    "file:/e:/sun/articles/vol13/src/CDRotation"
    
      width="500"
    
      height="600"
    
      align="Top"
    
      alt="If you had a java-enabled browser,
    
     you would see an applet here.">
    
    </applet>

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

    Рассмотрим наиболее важные методы нашего аплета.

    Метод start

    В задачу метода start, который получает управление при отображении окна аплета, входит создание и запуск потока, отображающего кадры видеофильма с изображением вращающегося компакт-диска:

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

    Поток создается как объект класса Thread, причем конструктору передается ссылка на главный класс аплета. Поэтому при запуске потока управление получит метод run, определенный в классе аплета.

    Метод stop

    Метод stop останавливает работу потока, когда окно аплета исчезает с экрана:

    if(m_CDRotation != null)
    
    {
    
      m_CDRotation.stop();
    
      m_CDRotation = null;
    
    }

    Для остановки вызывается метод stop.

    Метод paint

    Сразу после получения управления, метод paint закрашивает окно аплета белым цветом и рисует вокруг него черную рамку.

    Затем метод проверяет содержимое флага m_fAllLoaded. Этот флаг установлен в значение true, когда все кадры видеофильма загружены и сброшен в значение false, когда загрузка кадров еще не завершена. Последняя ситуация возникает всегда при первом вызове метода paint.

    Если все изображения загружены, метод paint вызывает метод displayImage, определенный в нашем приложении:

    if(m_fAllLoaded)
    
    {
    
      displayImage(g);
    
    }

    Этот метод, о котором мы еще расскажем подробнее, отображает в окне аплета текущий кадр видеофильма.

    Если же кадры видеофильма еще не загружены, в окне аплета отображается соответствующее сообщение:

    else
    
      g.drawString("Please, wait...", 
    
        10, dimAppWndDimension.height / 2);

    Метод run

    Метод run работает в рамках отдельного потока. Он занимается последовательным рисованием кадров нашего видеофильма.

    Прежде всего метод run записывает нулевое значение в поле m_nCurrImage, хранящее номер текущего отображаемого кадра:

    m_nCurrImage = 0;

    Далее выполняется проверка, загружены ли все кадры видеофильма, для чего анализируется содержимое флага m_fAllLoaded.

    Если изображения не загружены (а в самом начале так оно и есть) метод run перерисовывает окно аплета и получает контекст отображения для этого окна. Затем создается массив объектов Image для хранения кадров видеофильма:

    m_Images   = new Image[NUM_IMAGES];

    Метод run создает также объект класса MediaTracker для ожидания загрузки всех кадров видеофильма:

    MediaTracker tracker = 
    
      new MediaTracker(this);

    Далее метод run в цикле загружает изображения и добавляет их в объект класса MediaTracker для того чтобы можно было дождаться загрузки всех кадров:

    for (int i = 0; i < NUM_IMAGES; i++)
    
    {
    
      strImage = "images/cdimg0" +
    
       ((i < 10) ? "0" : "") + i + ".gif";
    
      m_Images[i] = getImage(
    
        getDocumentBase(), strImage);
    
      tracker.addImage(m_Images[i], 0);
    
    }

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

    Имена файлов, составляющих отдельные кадры, начинаются с префикса cdimg0, вслед за которым идет номер кадра (00, 01, 02, и так далее), и расширение имени .gif.

    Ожидание загрузки кадров выполняется с помощью метода waitForAll, о котором мы вам уже рассказывали:

    try
    
    {
    
      tracker.waitForAll();
    
      m_fAllLoaded = !tracker.isErrorAny();
    
    }
    
    catch (InterruptedException e)
    
    {
    
    }

    После окончания ожидания флаг завершения загрузки устанавливается только в том случае, если метод isErrorAny вернул значение false, то есть если не было никаких ошибок.

    Если же произошла ошибка, в окне аплета отображается соответствующее сообщение, после чего работа метода run (и, следовательно, работа созданного для него потока) заканчивается:

    if(!m_fAllLoaded)
    
    {
    
      stop();
    
      m_Graphics.drawString(
    
        "Load error",
    
        10, size().height / 2);
    
      return;
    
    }

    В случае удачной загрузки всех кадров метод run получает ширину и высоту первого кадра видеофильма и сохраняет эти значения в переменных m_nImgWidth и m_nImgHeight:

    m_nImgWidth  = 
    
      m_Images[0].getWidth(this);
    
    m_nImgHeight = 
    
      m_Images[0].getHeight(this);

    Далее окно аплета перерисовывается:

    repaint();

    При этом метод paint отображает в окне аплета первый кадр видеофильма.

    На следующем этапе работы метода run запускается цикл отображения кадров фильма:

    while (true)
    
    {
    
      try
    
      {
    
        displayImage(m_Graphics);
    
        m_nCurrImage++;
    
        if(m_nCurrImage == NUM_IMAGES)
    
          m_nCurrImage = 0;
    
        Thread.sleep(30);
    
      }
    
      catch (InterruptedException e)
    
      {
    
        stop();
    
      }  
    
    }

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

    Между отображением кадров выполняется задержка величиной 30 миллисекунд.

    Метод displayImage

    Метод displayImage вызывается из двух мест - из метода paint при перерисовке окна аплета и из метода run (периодически).

    Если кадры видеофильма не загружены, содержимое флага m_fAllLoaded равно false и метод displayImage просто возвращает управление, ничего не делая:

    if(!m_fAllLoaded)
    
      return;

    Если же загрузка изображений завершена, этот метод рисует в центре окна текущий кадр видеофильма, вызывая для этого знакомый вам метод drawImage:

    g.drawImage(m_Images[m_nCurrImage],
    
      (size().width - m_nImgWidth)   / 2,
    
      (size().height - m_nImgHeight) / 2,
    
       null);

    После того как кадр нарисован, мы надписываем на нем его порядковый номер, вызывая для этого метод drawString:

    g.drawString((new Integer(
    
      m_nCurrImage)).toString(),
    
      (size().width - m_nImgWidth)   / 2,
    
      ((size().height - m_nImgHeight) / 2) + 10);


Java | Продукты и решения | Технологии | Сервис и обучение
О компании | Партнеры | Новости | Поиск
Sun Microsystems Inc. Corporate Information Our partners News and Events Search on site Java Computing Products and Solutions Technologies and Researches Education and Service Content
Используются технологии uCoz