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

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

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

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

Приложение HorzScroll

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

Реализация эффекта бегущей его достаточно проста. Аплет создает задачу, которая периодически перерисовывает окно, вызывая метод repaint. Метод paint отображает строку в окне, каждый раз изменяя ее начальные координаты для получения эффекта сдвига.

Мы уверены, что вы сами легко справитесь с задачей создания бегущей строки, поэтому предложим вам кое-что иное. А именно, мы подготовили приложение, которое выписывает текстовую строку в своем окне последовательно буква за буквой. Когда вся строка будет нарисована, окно очищается и затем процесс возобновляется вновь (рис. 1.5).

Рис. 1.5. Окно аплета HorzScroll

В чем сложность создания такого аплета?

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

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

Исходные тексты приложения HorzScroll приведены в листинге 1.9.

Листинг 1.9. Файл HorzScroll\HorzScroll.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.*;

public class HorzScroll extends Applet implements Runnable
{
  // Ссылка на задачу рисования строки текста
  Thread m_HorzScroll = null;

  // Значения параметров по умолчанию
  private String m_Str   = "Hello from Java!";
  private String m_Fnt   = "Helvetica";
  private String m_style = "BOLD";
  private int m_size     = 12;
  private String m_color = "red";
  private int m_delay    = 50;

  // Имена параметров
  private final String PARAM_str   = "str";
  private final String PARAM_font  = "font";
  private final String PARAM_style = "style";
  private final String PARAM_size  = "size";
  private final String PARAM_color = "color";
  private final String PARAM_delay = "delay";

  // -------------------------------------------------------
  // getAppletInfo
  // Метод, возвращающей строку информации об аплете
  // -------------------------------------------------------
  public String getAppletInfo()
  {
    return "Name: HorzScroll\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";
  }

  // -------------------------------------------------------
  // getParameterInfo
  // Иинформация о параметрах
  // -------------------------------------------------------
  public String[][] getParameterInfo()
  {
    String[][] info =
    {
      { PARAM_str,   "String", "String to draw" },
      { PARAM_font,  "String", "Font name" },
      { PARAM_style, "String", "Font style" },
      { PARAM_size,  "String", "Font size" },
      { PARAM_color, "String", "String color" },
      { PARAM_delay, "int",    "Output delay" },
    };
    return info;    
  }

  // -------------------------------------------------------
  // init
  // Метод, получающий управление при инициализации аплета
  // -------------------------------------------------------
  public void init()
  {
    // Рабочая строка
    String param;

    // Получение значений параметров
    param = getParameter(PARAM_str);
    if (param != null)
      m_Str = param;

    param = getParameter(PARAM_font);
    if (param != null)
      m_Fnt = param;

    param = getParameter(PARAM_style);
    if (param != null)
      m_style = param;

    param = getParameter(PARAM_size);
    if (param != null)
      m_size = Integer.parseInt(param);

    param = getParameter(PARAM_color);
    if (param != null)
      m_color = param;

    param = getParameter(PARAM_delay);
    if (param != null)
      m_delay = Integer.parseInt(param);
  }

  // -------------------------------------------------------
  // paint
  // Метод paint, выполняющий рисование в окне аплета
  // -------------------------------------------------------
  public void paint(Graphics g)
  {
    // Определяем текущие размеры окна аплета
    Dimension dimAppWndDimension = size();

    // Определяем текущие размеры окна аплета
    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_HorzScroll == null)
    {
      m_HorzScroll = new Thread(this);
      m_HorzScroll.start();
    }
  }
  
  // -------------------------------------------------------
  // stop
  // Метод вызывается, когда окно аплета исчезает с экрана
  // -------------------------------------------------------
  public void stop()
  {
    if (m_HorzScroll != null)
    {
      m_HorzScroll.stop();
      m_HorzScroll = null;
    }
  }

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

    // Выбираем шрифт в контекст отображения
    if(m_style.equals("BOLD"))
      g.setFont(new Font(m_Fnt, Font.BOLD, m_size));

    else if(m_style.equals("ITALIC"))
      g.setFont(new Font(m_Fnt, Font.ITALIC, m_size));

    else 
      g.setFont(new Font(m_Fnt, Font.PLAIN, m_size));

    // Выбираем цвет в контекст отображения
    if(m_color.equals("red"))
      g.setColor(Color.red);

    else if(m_color.equals("green"))
      g.setColor(Color.green);

    else 
      g.setColor(Color.black);
    
    // Определяем размеры окна аплета
    Dimension dimAppWndDimension = size();

    // Определяем метрики текущего шрифта
    FontMetrics fm = g.getFontMetrics();

    // Номер текущего рисуемого символа строки
    int nCurrentChar = 0;

    // Позиция для рисования по вертикали
    int yPos = fm.getHeight() + 5;

    // Текущая позиция рисования символа по горизонтали
    int nCurrentXPos = 10;

    // Ширина текущего символа в пикселах
    int nCurrentCharWidth;
    
    // Бесконечный цикл рисования
    while (true)
    {
      try
      {
        try
        {
          // Определяем ширину текущего символа
          nCurrentCharWidth = 
            fm.charWidth(m_Str.charAt(nCurrentChar));

          // Массив для преобразования кода символа в сивол
          char[] ch;
    
          // Временная строка
          String s;

          // Создаем массив из одного элемента
          ch = new char[1];

          // Записыаем в него код нажатой клавиши
          ch[0] = m_Str.charAt(nCurrentChar);
    
          // Преобразуем в строку
          s = new String(ch);

          // Рисуем текущий символ в текущей позиции
          g.drawString(s, nCurrentXPos, yPos);

          // Увеличиваем текущую позицию на ширину
          // нарисованного символа
          nCurrentXPos += nCurrentCharWidth;

          // Переходим к следующему символу в строке
          nCurrentChar++;
        }
        // Обработка выхода за пределы строки
        catch (StringIndexOutOfBoundsException e)
        {
          // Сбрасываем номер текущего символа и
          // текущую позицию
          nCurrentChar = 0;
          nCurrentXPos = 10;

          // Перерисовываем окно аплета
          repaint();

          // Задержка после перерисовки окна
          try
          {
            Thread.sleep(500);
          }
          catch (InterruptedException ee)
          {
            stop();
          }
        }

        // Задержка между рисованием отдельных символов        
        Thread.sleep(m_delay);
      }
      catch (InterruptedException e)
      {
        stop();
      }
    }
  }
}

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

Листинг 1.10. Файл HorzScroll\HorzScroll.html


<html>
<head>
<title>HorzScroll</title>
</head>
<body>
<hr>
<applet
    code=HorzScroll.class
    id=HorzScroll
    width=170
    height=50 >
    <param name=str value="Hello from Java!">
    <param name=font value="Helvetica">
    <param name=style value="BOLD">
    <param name=size value="18">
    <param name=color value="red">
    <param name=delay value=100>
</applet>
<hr>
<a href="HorzScroll.java">The source.</a>
</body>
</html>

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

Аплет создает задачу отображения символов текстовой строки, для чего он реализует интерфейс Runnable (как и предыдущий аплет). Эта задача рисует отдельные символы текстовой строки, каждый раз определяя их ширину.

Поля класса HorzScroll

В поле m_HorzScroll хранится сслыка на задачу рсиования строки.

В документе HTML нашему аплету передается несколько параметров, задающих отображаемую строку и определяющих ее внешний вид.

В поле m_Str хранится отображаемая строка.

Шритф, стилевое оформление и размер смиволов строки хранится, соответственно, в полях m_Fnt, m_style и m_size. Цвет символов строки одинаковый и хранится в поле m_color.

Поле m_delay хранит текущее время задержки между отображением отдельных символов строки в миллисекундах.

Метод init

Метод init получает текущие значения параметров аплета и сохраняет их в соответствующих полях основного класса. Способ получения параметров аналогичен использованному в предыдущем приложении.

Метод paint

Метод paint просто закрашивает окно аплета желтым цветом и затем обводит его черной рамкой.

Метод run

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

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


Graphics g = getGraphics();

Затем в этом контексте отображения устанавливается шрифт с жирным, наклонным или обычным начертанием:


if(m_style.equals("BOLD"))
  g.setFont(new Font(m_Fnt, Font.BOLD, m_size));
else if(m_style.equals("ITALIC"))
  g.setFont(new Font(m_Fnt, Font.ITALIC, m_size));
else 
  g.setFont(new Font(m_Fnt, Font.PLAIN, m_size));

Обратите внимание, что название шрифта передается конструктору класса Font через первый параметр, а размер символов - через последний.

В зависимости от содержимого поля m_color метод run устанавливает один из трех цветов для отображения символов текстовой строки:


if(m_color.equals("red"))
  g.setColor(Color.red);
else if(m_color.equals("green"))
  g.setColor(Color.green);
else 
  g.setColor(Color.black);

Помимо этого, до запуска цикла метод run получает размеры окна аплета и метрики шрифта, только что установленного в контексте отображения:


Dimension dimAppWndDimension = size();
FontMetrics fm = g.getFontMetrics();

В переменную nCurrentChar, хранящую номер текущего отображаемого символа, записывается нулевое значение.

Кроме того, вычисляется позиция для рисования строки по вертикальной оси yPos и устанавливается начальная позиция первого символа строки по горизонтальной оси nCurrentXPos:


int yPos = fm.getHeight() + 5;
int nCurrentXPos = 10;

Далее метод run запускает бесконечный цикл рисования символов.

Первое, что метод run делает в этом цикле, это вычисление ширины текущего символа, сохраняя ее в переменной nCurrentCharWidth:


nCurrentCharWidth = 
  fm.charWidth(m_Str.charAt(nCurrentChar));

Текущий символ извлекается из строки при помощи метода charAt, определенном в классе String. Ширина извлеченного таким образом символа символа определяется методом charWidth из класса метрик шрифта FontMetrics.

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

С этим, однако, есть небольшая сложность - метод drawString не может отображать отдельные символы. Поэтому мы должны создать строку, состоящую из одного символа и передать эту строку методу drawString.

Эта задача решается достаточно просто.

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


char[] ch;
String s;
ch = new char[1];

В самый первый элемент массива мы записываем текущий символ:


ch[0] = m_Str.charAt(nCurrentChar);

Затем мы создаем строку из массива, пользуясь конструктором, специально предусмотренным для этой цели в классе String:


s = new String(ch);

Все! Теперь можно отображать строку, состоящую из одного символа, в текущей позиции:


g.drawString(s, nCurrentXPos, yPos);

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


nCurrentXPos += nCurrentCharWidth;
nCurrentChar++;

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

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

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