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

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

Оглавление
Кнопки Button

Кнопки с графикой и анимацией
Кнопка в виде аплета
Переключатели класса Checkbox
Переключатели с зависимой фиксацией
Нестандартные переключатели
Списки класса Choice
Списки класса List
Поля класса Label
Поля класса TextField
Поля класса TextArea
Нестандартные текстовые поля
Кнопки и события в JDK 1.1

Линейки Scrollbar
Окно ScrollPane

Назад Вперед

3.3. Кнопка в виде аплета

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

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

Исходный текст примера

Архив проекта для Java WorkShop 2.0

Демонстрация
(ваш браузер должен уметь работать с аплетами Java)

Немного теории

Для оформления ссылок в документах HTML часто используют кнопки в виде графических изображений кнопок. Однако эти кнопки не нажимаются, что является заметным недостатком.

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

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

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

Между тем нетрудно сделать аплет Java, который решит все перечисленные выше проблемы сразу.

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

Такой аплет может сам подписывать кнопки, поэтому вам нужно подготовить только два изображения - для нажатого и отжатого состояния кнопок. Если на странице расположено много кнопок (десять и больше), это может дать заметный выигрыш в скорости загрузки.

Описание примера

Основной класс аплета, представляющего собой кнопку, создан на базе Applet и дополнительно реализует интерфейс Runnable. Этот интерфейс необходим для анимации в многопоточном режиме.

Дополнительно к классам java.applet.* и java.awt.* мы включили библиотеку классов java.net.*. Она необходима для выполнения загрузки в окно браузера документа с заданным адресом URL.

Поля основного класса

Наш аплет принимает ряд параметров, определяющих внешний вид и режим работы кнопки. Ниже мы перечислили параметры аплета, название поля, в котором хранится значение этого параметра, а также краткое описание параметров:

Параметр Поле Описание
Width parmWidth Ширина окна кнопки
Height parmHeight Высота окна кнопки
ImageUp parmImageUp Графическое изображение кнопки в отжатом состоянии. Размеры этого изображения должны быть равны размерам окна кнопки
ImageDn parmImageDn Графическое изображение кнопки в нажатом состоянии
Animate parmAnimate Флаг анимации. Если значение равно true, при размещении курсора над поверхностью кнопки цвет надписи будет периодически меняться с черного на красный и обратно
Title parmTitle Надпись на поверхности кнопки
ShadowValue parmShadowValue Величина сдвига надписи для нажатой кнопки в пикселах
TitleFont parmTitleFont Шрифт для надписи на кнопке
TitleFontSize parmTitleFontSize Размер указанного выше шрифта
TitleBold parmTitleBold Выделение надписи жирным шрифтом
TitleItalic parmTitleItalic Выделение надписи наклоном
URL parmURL Адрес URL документа, который будет загружаться в окно браузера при нажатии на кнопку
URLWindow parmURLWindow Имя окна для загрузки указанного выше документа. Нужно главным образом для работы с фреймами

Вы не обязаны указывать все перечисленные параметры, так как они имеют значения по умолчанию:

private String parmWidth    = "80";
private String parmHeight   = "20";
private String parmImageUp  = "btnup.gif";
private String parmImageDn  = "btndn.gif";
private String parmAnimate  = "true";
private String parmTitle    = "Button";
private String parmShadowValue  = "1";
private String parmTitleFont = "Helvetica";
private String parmTitleFontSize = "12";
private String parmTitleBold    = "true";
private String parmTitleItalic  = "false";
private String parmURL  = null;
private String parmURLWindow  = "_self";

Если вас устраивают эти параметры, то можете ограничится указанием в документе HTML только параметров Title и URL.

В следующих полях хранятся преобразованные значения параметров аплета:

int nWidth   = 80;
int nHeight  = 20;
boolean bAnimate = true;
Image imgButtonUp;
Image imgButtonDn;
int nShadowValue;
boolean bTitileBold;
boolean bTitileItalic;
Dimension dimAppletWindow;
int nWindowWidth;
int nWindowHeight;
int nTitleFontSize;

Поле bButtonUp хранит текущее состояние кнопки (нажата или отжата):

boolean bButtonUp = true;

Значение true соответствует отжатой кнопке, значение false - нажатой.

В поле threadAnimate хранится ссылка на поток, в задачу которого входит анимация кнопки:

Thread threadAnimate = null;

Поле clrTitleColor хранит текущее значение цвета надписи, изменяющееся в процессе анимации:

Color clrTitleColor = Color.black;

И, наконец, последняя группа полей хранит имена параметров аплета:

private final String 
  name_parmWidth    = "Width";
private final String 
  name_parmHeight   = "Height";
private final String 
  name_parmImageUp  = "ImageUp";
private final String 
  name_parmImageDn  = "ImageDn";
private final String 
  name_parmAnimate  = "Animate";
private final String 
  name_parmTitle    = "Title";
private final String 
  name_parmShadowValue  = "ShadowValue";
private final String 
  name_parmTitleFont  = "TitleFont";
private final String 
  name_TitleFontSize  = "TitleFontSize";
private final String 
  name_TitleBold      = "TitleBold";
private final String 
  name_TitleItalic    = "TitleItalic";
private final String 
  name_URL        = "URL";
private final String 
  name_URLWindow  = "URLWindow";

Метод getParameterInfo

Метод getParameterInfo возвращает ссылку на массив описаний параметров аплета. Его исходный текст приведен ниже (в сокращенном виде):

public String[][] getParameterInfo()
{
  String[][] paramInfo = 
  {
    {
      name_parmWidth, 
        "String", "Button width"
    },
    {
      name_parmHeight,  
        "String", "Button height"
    },
     . . .
    {
      name_URLWindow, 
        "String", "URL window"
    }
  };
  return paramInfo;
}

Метод init

При инициализации аплета метод init прежде всего получает значения всех параметров. Если параметр не задан, используется значение по умолчанию.

Вот, например, как мы получаем значение параметра Width:

String parm;
parm = getParameter(name_parmWidth);
  if(parm != null)
    parmWidth = parm;

При помощи метода getParameter мы пытаемся получить значение параметра. Если этот метод возвращает null, значит параметр не задан. В этом случае мы просто оставляем в поле parmWidth то значение, которое указано при его определении.

Числовые параметры мы преобразуем следующим образом:

try
{  
  Integer intVal = new Integer(parmWidth);
  nWidth = intVal.intValue();
}
catch(Exception ex) {}

Так как числовой параметр может быть задан неверно, при работе конструктора объекта класса Integer возможно возникновение исключения. Мы игнорируем его, оставляя таким образом нетронутым значение, заданное по умолчанию.

Логические параметры обрабатываются следующим образом:

if(parmAnimate.equals("true"))
  bAnimate = true;
else
  bAnimate = false;

Для загрузки графических изображений кнопки мы создаем объекты класса Image:

imgButtonUp = 
  getImage(getCodeBase(), parmImageUp);
imgButtonDn = 
  getImage(getCodeBase(), parmImageDn);

Так как в качестве адреса URL файлов изображений мы указываем значение, полученное от метода getCodeBase, эти файлы должны находиться в том же каталоге сервера Web, что и файл байт-кода аплета.

На завершающем этапе метод init определяет текущие размеры окна аплета и сохраняет их в соответствующих полях:

dimAppletWindow = size();
nWindowWidth = dimAppletWindow.width;
nWindowHeight = dimAppletWindow.height;

Метод paint

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

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

int nFontStyle = Font.PLAIN;

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

if(bTitileBold)
  nFontStyle |= Font.BOLD;
     
if(bTitileItalic)
  nFontStyle |= Font.ITALIC;

Далее метод paint устанавливает в контексте отображения окна аплета шрифт, указанный в параметре аплета TitleFont:

g.setFont(new Font(parmTitleFont, 
  nFontStyle, nTitleFontSize));

После этого определяются метрики шрифта и выполняется позиционирование надписи по центру окна аплета:

FontMetrics fm = g.getFontMetrics();

int nTitileWidth = 
  fm.stringWidth(parmTitle);
int nTitleHeight = fm.getAscent() - 
  fm.getLeading() - fm.getDescent();
    
int x0 = 
  (nWindowWidth - nTitileWidth) / 2;
int y0 = 
  ((nWindowHeight - nTitleHeight) / 2) +
   nTitleHeight;

В поля x0 и y0 записываются координаты для рисования надписи.

Далее метод paint проверяет текущее состояние кнопки и выбирает соответствующее изображение для рисования в своем окне:

if(bButtonUp)
{
  g.drawImage(imgButtonUp, 0, 0, this);
  g.setColor(clrTitleColor);
  g.drawString(parmTitle, x0, y0);
}
else
{
  g.drawImage(imgButtonDn, 0, 0, this);
  g.setColor(Color.blue);
  g.drawString(parmTitle, 
    x0 - nShadowValue, y0 - nShadowValue);
}

После рисования графического изображения метод paint устанавливает текущий цвет надписи и рисует ее методом drawString.

Метод mouseDown

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

public boolean mouseDown(
  Event ev, int x, int y)
{
  if(bButtonUp)
  {
    bButtonUp = false;
    repaint();
    doButtonAction();
  }  
  return true;
}

Этот метод проверяет текущее состояние кнопки, и если она отжата, переводит кнопку в нажатое состояние. Для этого в поле bButtonUp записывается значение false.

Затем аплет перерисовывает свое окно и вызывает метод doButtonAction, загружающий в окно браузера документ HTML, адрес которого задан параметром аплета с именем URL.

Метод mouseUp

Этот метод просто переключает кнопку в отжатое состояние и затем перерисовывает окно аплета:

public boolean mouseUp(
  Event ev, int x, int y)
{
  if(!bButtonUp)
  {
    bButtonUp = true;
    repaint();
  }  
  return true;
}

Метод mouseEnter

Когда пользователь располагает курсор мыши над поверхностью окна нашего аплета, управление передается методу mouseEnter.

Он проверяет, задан ли в параметре аплета Animate режим анимации. Если задан, то метод mouseEnter запускает на выполнение поток анимации threadAnimate:

public boolean mouseEnter(
  Event ev, int x, int y)
{
  if(bAnimate)
  {
    if(threadAnimate == null)
    {
      threadAnimate = new Thread(this);
      threadAnimate.start();
    }
  }
  return true;
}

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

Метод mouseExit

Если пользователь убирает курсор из окна аплета, метод mouseExit останавливает запущенный ранее поток анимации:

public boolean mouseExit(
  Event ev, int x, int y)
{
  if(bAnimate)
  {
    if(threadAnimate != null)
    {
      threadAnimate.stop();
      threadAnimate = null;
      clrTitleColor = Color.black;
    }
  }
  bButtonUp = true;
  repaint();
  return true;
}

После остановки на поверхности кнопки устанавливается черный цвет надписи.

Эти действия выполняются только в том случае, если в параметре аплета Animate задан режим анимации

Метод stop

Когда документ с кнопками исчезает из окна браузера, метод stop останавливает запущенную ранее анимацию:

public void stop()
{
  if(bAnimate)
  {
    if(threadAnimate != null)
    {
      threadAnimate.stop();
      threadAnimate = null;
      clrTitleColor = Color.black;
    }
  }
}

Метод run

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

Его задача заключается в периодическом изменении цвета надписи, хранящегося в поле clrTitleColor. Эта операция выполняется в бесконечном цикле с задержкой на каждой итерации, равной 300 миллисекундам:

public void run()
{
  boolean bFlipFlop = true;
  while(true)
  {
    if(bFlipFlop)
    {
      clrTitleColor = Color.red;
      bFlipFlop = false;
    }
    else
    {
      clrTitleColor = Color.black;
      bFlipFlop = true;
    }

    repaint();

    try
    {
      Thread.sleep(300);
    }
    catch (InterruptedException ex)
    {
      stop();
    }
  }
}

При каждом проходе цикла окно аплета перерисовывается методом repaint.

Метод doButtonAction

Метод doButtonAction получает управление, когда пользователь нажимает на нашу кнопку. Исходный текст этого метода приведен ниже:

void doButtonAction()
{
  if(parmURL != null)
  {
    URL url = null;
    AppletContext appletContext;
    appletContext = getAppletContext();

    try
    {
      url = new URL(parmURL);
    }
    catch (MalformedURLException e) { }

    if (url != null)
    {
      appletContext.showDocument(
        url, parmURLWindow);
    }
  }
}

Здесь мы вначале получаем ссылку на контекст appletContext, в котором исполняется аплет. С помощью этой ссылки можно загрузить в окно браузера новый документ HTML и выполнить другие операции над браузером.

Перед загрузкой мы создаем новый объект класса URL, передавая ему строку из одноименного параметра аплета. Если создание прошло успешно, документ загружается методом showDocument в окно браузера, заданное параметром аплета URLWindow. В качестве имени окна вы можете использовать, в частности, имена окон фреймов, такие как _self, _top, _parent, а также имя _blank.


Назад Вперед

[Назад]