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


Метод paint


Наиболее интересен для нас метод paint, который выполняет рисование в окне аплета. Вот его исходный текст, созданный системой Java Applet Wizard:

public void paint(Graphics g)

{

  g.drawString(

    "Created with Microsoft Visual J++ Version 1.0",

    10, 20);

}

Если посмотреть определение класса Applet, то в нем нет метода paint. В каком же классе определен этот метод?

Взглянем на определение класса Applet:

public  class  java.applet.Applet

    extends  java.awt.Panel

{

  . . .



}

Во-первых, вы видите, что полное имя класса Applet есть java.applet.Applet. Включая оператором import библиотеку классов java.applet.*, мы включали и определение класса Applet.

Во-вторых, из определения класса можно заключить, что класс java.applet.Applet произошел от класса java.awt.Panel. Напомним, что определение классов java.awt.* также было включено в исходный текст нашего аплета оператором import.

Если класс java.applet.Applet был создан на базе класса java.awt.Panel, то нет ли в базовом классе определения метода paint?

Изучив исходный текст класса java.awt.Panel, убеждаемся, что такого метода там нет, однако сам класс java.awt.Panel произошел от класса java.awt.Container:

public  class  java.awt.Panel

    extends  java.awt.Container

{

  . . .

}

Продолжим наши исследования. В классе java.awt.Container снова нет метода paint, но сам этот класс создан на базе класса java.awt.Component:

public  abstract  class  java.awt.Container

    extends  java.awt.Component

{

  . . .

}

Но и здесь метода paint нет. Этот метод определен в классе java.awt.Component, который, в свою очередь, произошел от класса java.lang.Object и реализует интерфейс java.awt.image.ImageObserver:

public  abstract  class  java.awt.Component

    extends  java.lang.Object

    implements java.awt.image.ImageObserver

{

  . . .

}

Мы проследили иерархию классов от класса java.applet.Applet, на базе которого создан наш аплет, до класса java.lang.Object, который является базовым для всех классов в Java.


В обработчик метода paint мы добавили функции рисования.

В самом начале своей работы метод определяет текущие размеры  окна аплета, вызывая для этого метод size:

Dimension dimAppWndDimension = size();

Метод size определен в классе Component, от которого в конечном счете наследуется класс Applet и класс нашего приложения Painter. Этот метод возвращает ссылку на объект класса Dimension, хранящего высоту и ширину объекта:

public class java.awt.Dimension

  extends java.lang.Object

{

  // -----------------------------------------------------

  // Поля класса

  // -----------------------------------------------------

  public int height; // высота

  public int width;  // ширина

  // -----------------------------------------------------

  // Конструкторы

  // -----------------------------------------------------

  public Dimension();

  public Dimension(Dimension  d);

  public Dimension(int  width, int  height);

  // -----------------------------------------------------

  // Метод

  // -----------------------------------------------------

  public String toString();

}

На следующем шаге после определения размеров окна наше приложение рисует в окне строку, а затем стирает содержимое всего окна:

g.drawString("Невидимая строка", 10, 20);

g.clearRect(0, 0,

   dimAppWndDimension.width  - 1,

   dimAppWndDimension.height - 1);

В качестве начальных координат стираемой области мы указали точку (0, 0) - это верхний левый угол окна аплета. Ширина и высота стираемой области задана исходя из размеров аплета, полученных от метода size.

Для того чтобы изменить цвет фона окна, ме его закрашиваем (хотя могли бы воспользоваться и методом setBackground). Это можно сделать методом fillRect. Вначале при помощи метода setColor мы выбираем в контекст отображения желтый цвет, а затем закрашиваем всю внутреннюю область окна аплета методом fillRect:

g.setColor(Color.yellow);

g.fillRect(0, 0,

  dimAppWndDimension.width  - 1,

  dimAppWndDimension.height - 1);




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

FontMetrics fm = g.getFontMetrics();

yStep = fm.getHeight();

Зная высоту шрифта и количество элементов в списке доступных шрифтов, мы можем изменить размер окна аплета по вертикали таким образом, чтобы в нем поместились все строки. Количество элементов в массиве fntlist равно fntlist.length, а полную высоту шрифта мы только что определили. Для изменения высоты окна аплета мы используем метод resize:

resize(150, 20 + yStep * fntlist.length);

Далее мы определяем новые размеры окна аплета, закрашиваем фон окна желтым цветом и обводим окно тонкой рамкой черного цвета:

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);

Эту операцию мы уже выполняли в предыдущем приложении.

Список установленных шрифтов выводится достаточно просто в цикле:

for(int i = 0; i < fntlist.length; i++)

{

  g.drawString(fntlist[i], 10, yStart + yStep * i);

}

Здесь содержимое параметра цикла (переменной i) меняется от 0 до количества элементов в массиве length. Каждая новая строка рисуется со смещением, равным полной высоте символов текущего шрифта, выбранного в контекст отображения.




После закрашивания фона желтым цветом и рисования вокруг окна аплета черной рамки метод paint анализирует значение параметра m_Type1 и выбирает в контекст отображения шрифт для рисования первой строки:

if(m_Type1.equals("Bold"))

  g.setFont(new Font(m_Font1, Font.BOLD, 25));

else if(m_Type1.equals("Italic"))

  g.setFont(new Font(m_Font1, Font.ITALIC, 25));

else if(m_Type1.equals("Plain"))

  g.setFont(new Font(m_Font1, Font.PLAIN, 25));

Для сравнения строк класса String мы используем метод equals, который возвращает значение true при совпадении с заданной строкой и false в противном случае.

Методу выбора шрифта setFont мы передаем объект класса Font, созданный конструктором.

Конструктор получает в качетсве первого параметра содержимое поля класса m_Font1, которое соответствует значению параметра аплета с именем Font1.

Значение второго параметра (стиль шрифта) выбирается исходя из значения параметра аплета с именем m_Type1. Здесь мы указываем константы, определенные в классе Font.

И, наконец, третий параметр конструктора класса Font задает размер символов шрифта, равный 25 пикселам.

После выбора шрифта мы выполняем отступ от верхней границы окна и рисуем первую строку в позиции (0, yCurrent):

yCurrent += yStart;

g.drawString(m_Str1, 10, yCurrent);

На следующем этапе метод paint получает метрику только что выбранного шритфа и увеличивает текущую позицию yCurrent на величину полной высоты символов шрифта, полученную с помощью метода getHeight:

FontMetrics fm = g.getFontMetrics();

yCurrent += fm.getHeight();

Далее эта же процедура повторяется для остальный четырех отображаемых в окне аплета строк.

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




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

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

g.drawString("(" + ev.x + "," + ev.y + ")", ev.x, ev.y);




После обычной для наших аплетов раскраски фона и рисования рамки метод paint перебирает в цикле все элементы массива lines, рисуя линии:

for (int i=0; i < lines.size(); i++)

{

  Rectangle p = (Rectangle)lines.elementAt(i);

  g.drawLine(p.width, p.height, p.x, p.y);

}

Для объектов класса Vector можно использовать метода size, возвращающий количество элементов в массиве, чем мы воспользовались для проверки условия выхода из цикла.

Чтобы извлечь элемент массива по его номеру, мы воспользовались методом elementAt, передав ему через единственный параметр номер извлекаемого элемента.

Так как в массиве хранятся объекты класса Rectangle, перед инициализацией ссылки p мы выполняем преобразование типов.

Перед завершением работы метод paint сбрасывает признак рисования, записывая в поле bDrawing значение false:

bDrawing = false;




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




Метод paint не содержит никакого кода для рисования кнопок, так как эта задача решается в рамках класса Button. После раскрашивания фона окна аплета и рисования рамки вокруг него, метод paint пишет название нажатой кнопки в окне аплета с помощью метода drawString:

g.drawString("Button (\"" + sTextLabel + "\") pressed",

  10, 70);




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

Основная задача метода paint заключается в отображении в нижней части окна аплета списка включенных переключателей. Для формирования этой строки мы создаем объект s класса String:

String s = new String("> ");

Далее мы проверяем по очереди состояние всех переключателей с независимой фиксацией, дописывая к строке s название включенных переключателей:

if(chbox1.getState())

  s = s + chbox1.getLabel() + ", ";

if(chbox2.getState())

  s = s + chbox2.getLabel() + ", ";

if(chbox3.getState())

  s = s + chbox3.getLabel() + ", ";

Для определения текущего состояния переключателей мы вызываем метод getState. Этот метод возвращает значение true для включенного переключателя и false - для выключенного. Название переключателя легко определить с помощью метода getLabel.

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

if(rdbox1.getState())

  s = s + rdbox1.getLabel();

else if(rdbox2.getState())

  s = s + rdbox2.getLabel();

else if(rdbox3.getState())

  s = s + rdbox3.getLabel();

else if(rdbox4.getState())

  s = s + rdbox4.getLabel();

После завершения формирования строки s она отображается в окне аплета методом drawString:

g.drawString(s, 10, 150);




Обработчик метода paint рисует рамку вокруг окна аплета и текстовую строку в средней части этого окна.

Dimension dimAppWndDimension = size();

g.drawRect(0, 0,

  dimAppWndDimension.width  - 1,

  dimAppWndDimension.height - 1);

g.drawString("Смотри на цвет фона и текста!", 10, 50);

При этом мы не указали цвет фона, а также цвет изображения. При этом используются цвета, установленные методом action при выборе соответствующих строк из списков.




Обработчик метода paint рисует рамку вокруг окна аплета и текстовую строку в средней части этого окна.

В нижней части окна аплета метод paint отображает выделенные в списках цвета фона и изображения:

g.drawString("Background:  " + sSelBackground, 10, 160);

g.drawString("Foreground:  " + sSelForeground, 10, 190);




Единственное, что делает метод paint, - это рисование рамки черного цвета вокруг окна аплета.




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

g.drawString("> " + str, 10, 100);




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

g.drawString("> " + str, 10, 100);




Метод paint рисует в окне панели pDraw, а не в главном окне аплета. Для этого метод paint получает контекст отображения этой панели, вызывая для этого метод getGraphics:

Graphics gpDraw;

gpDraw = pDraw.getGraphics();

Далее метод paint определяет размеры панели pDraw и рисует рамку вокруг окна этой панели:

Dimension dimAppWndDimension = pDraw.size();

gpDraw.drawRect(0, 0, dimAppWndDimension.width  - 1,

  dimAppWndDimension.height - 1);

После того как рамка будет нарисована, метод paint устанавливает в панели pDraw шрифт, название которого хранится в староке sFontName. Для этого используется контекст отображения gpDraw, полученный нами ранее для панели pDraw:

gpDraw.setFont(new Font(sFontName, Font.PLAIN, 12));

Текстовая строка отображается с использованием текущего цвета изображения и текущего шрифта, установленного в контексте отображения gpDraw, при помощи метода drawString:

gpDraw.drawString("Смотри на шрифт, цвет фона и текста!",

  10, 50);

Затем метод paint обводит панель блокнота рамкой. Вначале он получает контекст отображения для панели блокнота, как это показано ниже:

gpDraw = pCardPanel.getGraphics();

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

dimAppWndDimension = pCardPanel.size();

gpDraw.drawRect(0, 0, dimAppWndDimension.width  - 1,

  dimAppWndDimension.height - 1);



Содержание раздела