Информатика и информационные технологии Электротехника История искусства Каталог графических примеров

Аплет 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);
Назад Вперед
Начертательная геометрия и инженерная графика, перспектива