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

Microsoft Visual J++. Создание приложений и аплетов на языке Java. Часть 2

© Александр Фролов, Григорий Фролов
Том 32, М.: Диалог-МИФИ, 1997, 288 стр.

[Назад] [Содеожание] [Дальше]

Приложение Rectangles

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

Рис. 1.2. Окно аплета Rectangles

В результате в каждый момент времени перерисовывается только часть окна аплета и мерцание отсутствует.

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

Исходный файл приложения Rectangles приведен в листинге 1.3.

Листинг 1.3. Файл Rectangles\Rectangles.java


// =========================================================
// Рисование прямоугольников в отдельной задаче
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW:    http://www.glasnet.ru/~frolov
//            или
//         http://www.dials.ccas.ru/frolov
// =========================================================
import java.applet.*;
import java.awt.*;
import java.util.*;

public class Rectangles extends Applet implements Runnable
{
  // Ссылка на задачу рисования прямоугольников
  Thread m_Rectangles = null;

  // -------------------------------------------------------
  // getAppletInfo
  // Метод, возвращающей строку информации об аплете
  // -------------------------------------------------------
  public String getAppletInfo()
  {
    return "Name: Rectangles\r\n" +
      "Author: Alexandr Frolov\r\n" +
      "E-mail: frolov@glas.apc.org" +
      "WWW:    http://www.glasnet.ru/~frolov" +
      "Created with Microsoft Visual J++ Version 1.0";
  }

  // -------------------------------------------------------
  // paint
  // Метод paint, выполняющий рисование в окне аплета
  // -------------------------------------------------------
  public void paint(Graphics g)
  {
    // Определяем текущие размеры окна аплета
    Dimension dimAppWndDimension = size();
    
    // Выбираем в контекст отображения желтый цвет
    g.setColor(Color.yellow);
    
    // Закрашиваем внутреннюю область окна аплета
    g.fillRect(0, 0, 
      dimAppWndDimension.width  - 1, 
      dimAppWndDimension.height - 1);

    // Выбираем в контекст отображения черный цвет
    g.setColor(Color.black);

    // Рисуем рамку вокруг окна аплета
    g.drawRect(0, 0, 
      dimAppWndDimension.width  - 1, 
      dimAppWndDimension.height - 1);
  }

  // -------------------------------------------------------
  // start
  // Метод вызывается при первом отображении окна аплета
  // -------------------------------------------------------
  public void start()
  {
    if (m_Rectangles == null)
    {
      m_Rectangles = new Thread(this);
      m_Rectangles.start();
    }
  }
	
  // -------------------------------------------------------
  // start
  // Метод вызывается при первом отображении окна аплета
  // -------------------------------------------------------
  public void stop()
  {
    if (m_Rectangles != null)
    {
      m_Rectangles.stop();
      m_Rectangles = null;
    }
  }

  // -------------------------------------------------------
  // run
  // Метод, который работает в рамках отдельной задачи
  // Он рисует в окне аплета прямоугольники случайного
  // цвета, размера и расположения
  // -------------------------------------------------------
  public void run()
  {
    // Получаем контекст отображения для окна аплета
    Graphics g = getGraphics();

    // Определяем текущие размеры окна аплета
    Dimension dimAppWndDimension = size();

    while (true)
    {
      int x, y, width, height;
      int rColor, gColor, bColor;
      
      // Выбираем случайным образом размеры
      // и расположение рисуемого прямоугольника
      x = (int)(dimAppWndDimension.width *
           Math.random());
      y = (int)(dimAppWndDimension.height * 
           Math.random());
      width = (int)(dimAppWndDimension.width * 
           Math.random()) / 2;
      height = (int)(dimAppWndDimension.height * 
           Math.random()) / 2;
      
      // Выбираем случайный цвет для 
      // рисования прямоугольника
      rColor = (int)(255 * Math.random());
      gColor = (int)(255 * Math.random());
      bColor = (int)(255 * Math.random());

      // Устанавливаем выбранный цвет 
      // в контексте отображения
      g.setColor(new Color(rColor, gColor, bColor));

      // Рисуем прямоугольник
      g.fillRect(x, y, width, height);

      // Выполняем задержку на 50 миллисекунд
      try
	{
	  Thread.sleep(50);
	}
	catch (InterruptedException e)
	{
	  stop();
	}
    }
  }

  // -------------------------------------------------------
  // mouseEnter
  // Метод вызывается, когда курсор мыши оказывается над
  // окном аплета
  // -------------------------------------------------------
  public boolean mouseEnter(Event evt, int x, int y)
  {
    if (m_Rectangles != null)
    {
      // Когда курсор мыши оказывается над поверхностью
      // окна аплета, временно приостанавливаем
      // задачу рисования прямоугольников
      m_Rectangles.suspend();
    }
    return true;
  }

  // -------------------------------------------------------
  // mouseExit
  // Метод вызывается, когда курсор мыши покидает
  // окно аплета
  // -------------------------------------------------------
  public boolean mouseExit(Event evt, int x, int y)
  {
    if (m_Rectangles != null)
    {
      // Когда курсор мыши покидает окно аплета,
      // возобновляем работу задачи рисования 
      // прямоугольников
      m_Rectangles.resume();
    }
    return true;
  }
}

В листинге 1.4 находится исходный текст документа HTML, созданного автоматически для нашего аплета.

Листинг 1.4. Файл Rectangles\Rectangles.html


<html>
<head>
<title>Rectangles</title>
</head>
<body>
<hr>
<applet
    code=Rectangles.class
    id=Rectangles
    width=320
    height=240 >
</applet>
<hr>
<a href="Rectangles.java">The source.</a>
</body>
</html>

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

Для создания задачи аплет Rectangles реализует интерфейс Runnable, то есть использует второй из описанных нами методов, как и предыдущий аплет.

Ниже мы рассмотрим наиболее важные методы аплета Rectangles.

Метод paint

В предыдущем приложении метод paint периодически получал управление в результате периодического вызова метода repaint, выполняемого отдельной задачей. Метод paint аплета Rectangles вызывается только при инициализации и тогда, когда нужно обновить окно аплета. Этот метод определяет текущие размеры окна аплета, закрашивает окно желтым цветом и рисует вокруг окна черную рамку.

Метод start

Когда пользователь начинает просмотр документа HTML, содержащего наш аплет, метод start создает и запускает задачу. Для создания задачи мы используем оператор new, а для старта задачи - метод start класса Thread:


public void start()
{
  if (m_Rectangles == null)
  {
    m_Rectangles = new Thread(this);
    m_Rectangles.start();
  }
}

Обратите внимание, что мы передаем конструктору класса Thread параметр this - ссылку на аплет. В результате роль задачи, работающей параллельно с кодом аплета, будет выполнять метод run, определенный в классе аплета.

Ссылка на созданную задачу записывается в поле m_Rectangles.

Метод stop

Метод stop нашего аплета не имеет никаких особенностей. Он вызывается, когда пользователь покидает страницу сервера Web с аплетом. В этом случае метод останавливает задачу, вызывая для этого метод stop класса Thread:


public void stop()
{
  if (m_Rectangles != null)
  {
    m_Rectangles.stop();
    m_Rectangles = null;
  }
}

После остановки в поле m_Rectangles записывается значение null. Это является признаком того, что задача остановлена.

Метод run

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

Для того чтобы рисовать, необходимо получить контекст отображения. Так как наша задача, точнее, метод run определен в классе аплета, то он может получить контекст отображения, вызвав метод getGraphics:


Graphics g = getGraphics();

Для рисования нам также нужно знать размеры окна аплета. Мы получаем эти размеры при помощи метода size:


Dimension dimAppWndDimension = size();

Вооружившись контекстом отображения и размерами окна аплета, задача входит в бесконечный цикл рисования прямоугольников.

В качестве генератора случайных чисел мы используем метод random из класса Math, который при каждом вызове возвращает новое случайное число типа double, лежащее в диапазоне значений от 0.0 до 1.0.

Координаты по осям X и Y рисуемого прямоугольника определяются простым умножением случайного числа, полученного от метода random, соответственно, на ширину и высоту окна аплета:


x = (int)(dimAppWndDimension.width  * Math.random());
y = (int)(dimAppWndDimension.height * Math.random());

Аналогично определяются размеры прямоугольника, однако чтобы прямоугольники не были слишком крупными, мы делим полученные значения на 2:


width  = (int)(dimAppWndDimension.width * Math.random())/2;
height = (int)(dimAppWndDimension.height * Math.random())/2;

Так как случайное число имеет тип double, в обоих случаях мы выполняем явное преобразование результата вычислений к типу int.

Для случайного выбора цвета прямоугольника мы вычисляем отдельные цветовые компоненты, умножая значение, полученное от метода random, на число 255:


rColor = (int)(255 * Math.random());
gColor = (int)(255 * Math.random());
bColor = (int)(255 * Math.random());

Полученные значения цветовых компонент используются в конструкторе Color для получения цвета. Этот цвет устанавливается в контексте отображения методом setColor:


g.setColor(new Color(rColor, gColor, bColor));

Теперь все готово для рисования прямоугольника, которое мы выполняем при помощи метода fillRect:


g.fillRect(x, y, width, height);

После рисования прямоугольника метод run задерживает свою работу на 50 миллисекунд, вызывая метод sleep:


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

Для обработки исключения InterruptedException, которое может возникнуть во время работы этого метода, мы предусмотрели блок try - catch. При возникновении указанного исключения работа задачи останавливается вызовом метода stop.

Метод mouseEnter

В предыдущем томе “Библиотеки системного программиста” мы рассказывали о методах mouseEnter и mouseExit. Первый из этих методов вызывается, когда в результате перемещения курсор мыши оказывается над окном аплета, а второе - когда курсор покидает окно аплета. Мы переопределили эти методы в своем аплете.

Когда курсор мыши оказывается над окном аплета, мы временно приостанавливаем работу задачи, вызывая метод suspend:


public boolean mouseEnter(Event evt, int x, int y)
{
  if (m_Rectangles != null)
  {
    m_Rectangles.suspend();
  }
  return true;
}

Преостановленная задача не уничтожается. Ее работа может быть продолжена с помощью метода resume.

Метод mouseExit

Когда курсор мыши покидает окно аплета, вызывается метод mouseExit. Этот метод в нашем аплете возобновляет работу задачи, временно приостановленной методом suspend. Для этого используется метод resume, как это показано ниже:


public boolean mouseExit(Event evt, int x, int y)
{
  if (m_Rectangles != null)
  {
    m_Rectangles.resume();
  }
  return true;
}
[Назад] [Содеожание] [Дальше]