}

}

class Square extends Figure

{

public double side;

public Square(int x, int y, int width)

{

super(x, y, width, width);

side=width;

}

public double getArea()

{

return (side * side);

}

public double getPerimeter()

{

return (4 * side);

}

public void show(Graphics g)

{

g. setColor(Color. cyan);

g. fillRect(x, y,(int)side,(int)side);

}

}

И, наконец, для тестирования этих классов создан класс, производный от Applet. Обратите внимание, что в функции перерисовки paint ничего не говорится о том, какая именно фигура будет изображаться. Для рисования фигуры вызывается метод show именно того объекта, который был создан в функции init. Таким образом, тип объекта определяется только на этапе выполнения.

public class Poly extends Applet

{

Figure myFigure;

public void init()

{

switch ((int)(Math. random()*2))

{

case 0:

myFigure = new Circle((int)(Math. random()*100),

(int)(Math. random()*100),

10+(int)(Math. random()*100));

break;

case 1:

myFigure = new Square((int)(Math. random()*100),

(int)(Math. random()*100),

10+(int)(Math. random()*100));

break;

}

}

public void paint(Graphics g)

{

myFigure. show(g);

g. setColor(Color. black);

g. drawString("Площадь="+myFigure. getArea(),5, 25);

g. drawString("Периметр="+myFigure. getPerimeter(),

5, 45);

}

}

Внутренние классы

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

НЕ нашли? Не то? Что вы ищете?

Следующий пример рассмотрен подробно в параграфе AWT и обработка событий.



Так, в этом примере взаимодействуют три объекта:

§  класса, производного от Applet;

§  класса Panel для элементов управления;

§  класса, производного от Canvas для рисования.

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

Глава 3. Разработка апплетов

Работа с графикой

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

public void paint(Graphics g)

{ }

Этот метод вызывается в тех случаях, когда с точки зрения браузера необходима перерисовка всего окна апплета или его части. Для принудительной перерисовки апплета программным образом вызывайте метод repaint. Как видим, в качестве параметра метод paint получает графический контекст.

Для рисования простых графических объектов класс Graphics имеет методы:

drawLine(int x1, int y1, int x2, int y2)

рисование линии

drawRect(int x1, int y1, int x2, int y2)

рисование контура прямоугольника

fillRect(int x1, int y1, int x2, int y2)

рисование прямоугольника, заполненного текущим цветом

fillPolygon(int x[], int y[], int count)

рисование многоугольника, заполненного текущим цветом

и т. п.

Рассмотрим пример Графические примитивы.

import java. applet.*;

import java. awt.*;

public class Primitives extends Applet

{

public void paint(Graphics g)

{

int pointX[]={100, 180, 10, 190, 30};

int pointY[]={10, 180,30,70,190};

g. setColor(Color. red);

g. fillRoundRect(205,25,100,50,20,20);

g. setColor(Color. yellow);

g. fillRoundRect(225,45,100,50,20,20);

g. setColor(Color. green);

g. fillRoundRect(245,65,100,50,20,20);

g. setColor(Color. blue);

g. fillPolygon(pointX, pointY, pointX. length);

}

}


Для назначения текущего цвета используется метод setColor(Color) класса Graphics.

Задание для самостоятельной работы

Рассмотрите более подробно класс Color.

Работа со шрифтами

Для работы со шрифтами используется класс Font. Конструктор класса Font выглядит следующим образом:

Font(String название, int стиль, int размер)

Класс содержит несколько полезных статических переменных:

BOLD

жирное начертание

ITALIC

курсивное начертание

PLAIN

обычное начертание

Для примера создадим объект шрифт семейства TimesRoman размером 18 pt, жирного начертания:

Font font=new Font ("TimesRoman", Font. BOLD, 18);

Для того чтобы назначить созданный шрифт в качестве текущего, используется метод setFont класса Graphics:

public void paint(Graphics g)

{

g. setFont(font);

g. drawString(Mes, 10, 10);

}

Получить разнообразные характеристики шрифта можно с помощью объектов класса FontMetrics. Создадим объект класса FontMetrics на основе существующего шрифта:

public void paint(Graphics g)

{

FontMetrics fm;

Font BigFont=new Font("TimesRoman", Font. BOLD, 36);

g. setFont(BigFont);

fm=g. getFontMetrics();

// ....

}

Далее можно, например, получить размер строк или отдельных символов данного шрифта (в пикселах):

x = fm. charWidth('Щ'); // ширина буквы Щ
y = fm. stringWidth("Изучаем Java!");

// ширина строки "Изучаем Java!"

Задание для самостоятельной работы

Изучите более подробно методы классов Font и FontMetrics.

Передача внешних данных в апплет.


Вы уже знаете, что для размещения апплета на HTML-странице используется контейнер <applet></applet>. Кроме того, в апплет можно передать параметры, например:

<APPLET CODE=Star WIDTH=220 HEIGHT=220>

<PARAM name=x value='100'>

</APPLET>

Каждый параметр должен иметь имя – name (регистр в имени не учитывается) и значение – value.

В данном примере из HTML-документа в апплет Star. class могут передаваться разные значения параметра color:

<html><head></head>

<body bgcolor=Black bottommargin=0 leftmargin=0

topmargin=0 rightmargin=0>

<APPLET CODE=Star WIDTH=220 HEIGHT=220>

<PARAM name=color value='red on black'></APPLET>

</body></html>

Апплет получает параметры с помощью функции getParameter, обычно ее вызов размещают в функции инициализации:

import java. applet.*;

import java. awt.*;

public class Star extends Applet

{

String col;

public void init()

{

col=getParameter("color");

}

public void paint(Graphics g)

{

if (col. equals("black on red"))

{

g. setColor(Color. black);

setBackground(Color. red);

}

else if (col. equals("red on black"))

{

g. setColor(Color. red);

setBackground(Color. black);

}

else

{

g. setColor(Color. blue);

}

int pointX[]={100, 180, 10, 190, 30};

int pointY[]={10, 180, 30, 70, 190};

g. fillPolygon(pointX, pointY, pointX. length);

}

}

Запомните, что функция getParameter возвращает значение типа String. Если нужно получить числовые значения, придется выполнить преобразование, как в следующем примере.


В следующем примере из HTML-страницы в апплет Star2.class передаются 3 целых числа – интенсивность цвета (от 0 до 255)

<html><head></head>

<body bgcolor=Black bottommargin=0 leftmargin=0 topmargin=0 rightmargin=0>

<APPLET CODE=Star2 WIDTH=220 HEIGHT=220>

<PARAM name=red value=0>

<PARAM name=green value=200>

<PARAM name=blue value=150></APPLET>

</body></html>

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

import java. applet.*;

import java. awt.*;

public class Star2 extends Applet

{

int r, g,b;

public void init()

{

r=Integer. parseInt(getParameter("red"));

g=Integer. parseInt(getParameter("green"));

b=Integer. parseInt(getParameter("blue"));

}

public void paint(Graphics gr)

{

gr. setColor(new Color(r, g,b));

int pointX[]={100, 180, 10, 190, 30};

int pointY[]={10, 180, 30, 70, 190};

gr. fillPolygon(pointX, pointY, pointX. length);

}

}

Обратите внимание, что строковые значения параметров с помощью статической функции parseInt класса Integer преобразуются в целые числа.

Еще более громоздко выглядит преобразование параметра в число с плавающей точкой. Предположим, мы имеем переменную xmin типа double и параметр xMin. Преобразование параметра будет выглядеть:

xmin=(Double. valueOf(getParameter("xMin"))).doubleValue();

Разберите это выражение самостоятельно.

Существует другой способ передачи данных из HTML-страницы в апплет. Средствами языка клиентских сценариев JavaScript можно вызывать любой public-метод апплета, который определен в HTML-документе. Тем самым дается возможность перестройки, изменения состояния апплета уже после загрузки его в браузер. Для этого требуется в тэге <applet> указать значение атрибута name. После этого любой public-метод апплета вызывается с помощью следующей команды JavaScript:

document. имяАпплета. имяМетода(параметрыМетода)

Добавим в апплет Star2 метод, который позволяет изменять цвет нарисованной звезды.

public void UserColor(int Red, int Green, int Blue)

{

// запоминаем параметры метода в переменных класса

r=Red; g=Green; b=Blue;

// инициируем перерисовку изображения

repaint();

}

Для вызова метода уже загруженного апплета с именем app

<APPLET CODE=Star2 NAME=app WIDTH=220 HEIGHT=220>

<PARAM name=red value=0>

<PARAM name=green value=200>

<PARAM name=blue value=150>

</APPLET>

создадим следующие командные кнопки в HTML-документе с апплетом, при нажатии на которые звезда будет рисоваться ярко красным, зеленым и синим цветами, соответственно:

<input type="button" value="Красный" onclick="document. app. UserColor(255,0,0)">

<input type="button" value="Зеленый" onclick="document. app. UserColor(0,255,0)">

<input type="button" value="Синий" onclick="document. app. UserColor(0,0,255)">

Задание для самостоятельной работы

Измените цвет фона в апплете. Какому классу принадлежит эта функция?

AWT и обработка событий

В апплетах иногда бывает нужно разместить разнообразные управляющие элементы – текстовые поля, кнопки, списки и т. п. Для этого в языке Java существует технология, которая называется Abstract Window Toolkit. В этой технологии не используется привычный для нас принцип размещения элементов "левый верхний угол – ширина – высота". Вместо этого применяются так называемые "менеджеры раскладок" (layout managers).

FlowLayout – потоковая раскладка – используется в апплетах по умолчанию и предполагает, что элементы размещаются последовательно слева направо (точно так же, как в языке HTML). По умолчанию элементы центрируются и при изменении размеров апплета не изменяют свои размеры, а просто переупорядочиваются:

public class Flowlay extends Applet

{

public void init()

{ add(new Button("Кнопка1"));

add(new Button("Кнопка2"));

add(new Button("Кнопка3"));

add(new Button("Кнопка4")); }

}

GridLayout – табличная раскладка – используется в том случае, если элементы удобно размещать в табличном порядке. Количество ячеек и строк таблицы определяется при создании объекта GridLayout. По умолчанию элемент заполняет ячейку таблицы полностью (можно задать размер отступа элемента от границы ячейки) и изменяет свои размеры при изменении размеров контейнера, в котором он содержится. По умолчанию ячейки таблицы заполняются слева направо, сверху вниз.

public class Gridlay extends Applet

{

public void init()

{ setLayout(new GridLayout(2,2));

add(new Button("Кнопка1"));

add(new Button("Кнопка2"));

add(new Button("Кнопка3"));

add(new Button("Кнопка4")); }

}

BorderLayout – раскладка "по сторонам света" – использует структуру, показанную на рисунке внизу. Если какая-либо область остается пустой, то для нее место не выделяется. Элемент управления растягивается по размеру области, также можно задать зазор между областями.

Север

З
а
п
а
д

Центр

В
о
с
т
о
к

Юг

public class Borderlay extends Applet

{

public void init()

{ setLayout(new BorderLayout(10,10));

add("North", new Button("Кнопка1"));

add("Center", new Button("Кнопка2"));

add("East", new Button("Кнопка3"));

add("West", new Button("Кнопка4"));

add("South", new Button("Кнопка5"));

}

}

Для создания управляющих элементов используется операция new, вызывающая соответствующий конструктор. После создания элемента его нужно включить в состав контейнера (в самом простом случае – в состав апплета) с помощью метода add.

Создание кнопки:

Button MyButton = new Button("OK");

// параметр - надпись на кнопке

add(MyButton);

Создание текстового поля:

TextField MyText=new TextField("100", 5);

// параметры - значение и размер

add(MyText);

Создание флажка:

MyCheckbox=new Checkbox("название флажка", true);

// второй параметр - включен или выключен флажок

add(MyCheckbox);

Создание группы радиокнопок:

CheckboxGroup bkcolor= new CheckboxGroup();

Checkbox cb1= new Checkbox("белый фон", true, bkcolor);

Checkbox cb2= new Checkbox("голубой фон", false, bkcolor);

add(cb1);

add(cb2);

Создание списка:

Choice color=new Choice();

color. addItem("Черный");

color. addItem("Синий");

color. addItem("Красный");

color. addItem("Зеленый");

add(color);

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

·  ActionListener (для текстовых полей и кнопок) и/или

·  ItemListener (для списков, флажков и радиокнопок),

например,

public class Spir extends Applet

implements ActionListener, ItemListener

{ }

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

MyButton. addActionListener(this); MyText. addActionListener(this);

MyCheckbox. addItemListener(this);

// Для списка назначается один слушатель

color. addItemListener(this);

// В наборе радиокнопок слушатель назначается для каждой кнопки

cb1.addItemListener(this);

cb2.addItemListener(this);

Класс, раскрывающий интерфейс ActionListener, должен предоставлять код для метода actionPerformed, например

public void actionPerformed(ActionEvent e)

{

if (e. getSource()==MyText)

System. out. println

("Произошло событие для текстового поля");

if (e. getSource()==MyButton)

System. out. println("Произошло событие для кнопки");

}

Класс, раскрывающий интерфейс ItemListener, должен предоставлять код для метода itemStateChanged, например

public void itemStateChanged(ItemEvent e)

{

if (e. getItemSelectable()==color)

{

System. out. println((String)e. getItem());

}

if (e. getSource()==cb1)

System. out. println("Выбран белый фон");

if (e. getSource()==cb2)

System. out. println("Выбран голубой фон");

if (e. getSource()==MyCheckbox)

if(e. getStateChange()==1)

System. out. println("Флажок включен");

else

System. out. println("Флажок выключен");

}

Заметим, что флажок имеет два состояния – включен или выключен. Так что при возникновении события с флажком должно анализироваться состояние флажка. Это позволяет делать метод getStateChange класса ItemEvent, который возвращает 1, если флажок перешел в состояние "выбран", и 2 в противном случае.

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

Panel p1=new Panel(); // панель для элементов управления setLayout(new BorderLayout());

add("North",p1); // размещаем панель на апплете

p1.add(MyButton); // размещаем элементы на панели

p1.add(MyText);

p1.add(MyCheckbox);

p1.add(cb1);

p1.add(cb2);

p1.add(color);

В качестве примера рассмотрим подробно следующий апплет.

В заголовке апплета указано, что он раскрывает интерфейсы ItemListener (для работы со списком) и ActionListener (для работы с текстовым полем) В апплете определены переменные:

private int n=20; // количество пикселов в единице

private String name=""; // название функции

private Choice tip=new Choice(); // элемент - список

private TextField size; // элемент - текстовое поле

Panel p1=new Panel(); // панель для элементов управления

MyCanvas p2=new MyCanvas(); // канва для рисования

Апплет разбит на 2 части: верхняя – панель для элементов управления (объект класса Panel), нижняя – канва для рисования (объект пользовательского класса MyCanvas). Метод init апплета имеет вид:

public void init()

{

// назначаем менеджер раскладок для апплета

setLayout(new BorderLayout());

// назначаем менеджер раскладок для панели управления

p1.setLayout(new GridLayout(2,2));

// размещаем панель в северной части апплета

add("North",p1);

// размещаем канву в центральной части апплета

add("Center",p2);

// создаем метку и включаем ее в панель

p1.add(new Label("Выбирайте функцию: "));

// создаем элементы списка

tip. addItem("Синус");

tip. addItem("Косинус");

tip. addItem("Тангенс");

// назначаем слушателя для списка

tip. addItemListener(this);

// включаем список в панель

p1.add(tip);

// создаем метку и включаем ее в панель

p1.add(new Label("Пикселов в единичном отрезке:"));

// создаем текстовое поле

size=new TextField(""+n,5);

// включаем текстовое поле в панель

p1.add(size);

// назначаем слушателя для текстового поля

size. addActionListener(this);

}

Поскольку апплет раскрывает интерфейс ItemListener, он должен содержать функцию

public void itemStateChanged(ItemEvent e)

// параметр функции - событие

{

// из переменной-события получаем, какой объект его вызвал;

// эту проверку можно было не делать, поскольку у нас

// всего один объект мог вызвать данное событие

if (e. getItemSelectable()==tip)

{

// получаем выбранную строку из списка

name=(String)e. getItem();

// выполняем принудительную перерисовку канвы

p2.repaint();

}

}

Поскольку апплет раскрывает интерфейс ActionListener, он должен содержать функцию

public void actionPerformed(ActionEvent e)

// параметр функции - событие

{

// из переменной-события получаем, какой объект его вызвал;

// эту проверку можно было не делать, поскольку у нас

// всего один объект мог вызвать данное событие

if (e. getSource()==size)

{

// получаем значение из текстового поля и

// преобразуем его в целое число

n=Integer. parseInt(size. getText());

// выполняем принудительную перерисовку канвы

p2.repaint();

}

}

И, наконец, определяем канву для рисования – класс MyCanvas как внутренний класс апплета.

// Панель для рисования

class MyCanvas extends Canvas

{

int M, // ширина панели

N, // высота панели

x, y, xold, yold;

public void paint (Graphics g)

{

M=getSize().width;

N=getSize().height;

setBackground(new Color(200,200,200));

g. drawLine(M/2,0,M/2,N);

g. drawLine(0,N/2,M, N/2);

for (x=0; x<M; x++)

{

if (name. equals("Синус"))

{

y=(int)(N/2-Math. sin((double)(x-M/2)/n)*n);

}

else if (name. equals("Косинус"))

{

y=(int)(N/2-Math. cos((double)(x-M/2)/n)*n); }

else if (name. equals("Тангенс"))

{

y=(int)(N/2-Math. tan((double)(x-M/2)/n)*n); }

else return;

if (x==0) { xold=x; yold=y; }

g. drawLine(xold, yold, x, y);

xold=x; yold=y;

}

}

}

Почему здесь удобно использовать внутренний класс? Дело в том, что канва при рисовании использует переменные из апплета: название функции и масштаб числовых осей. В качестве внутреннего класса канва получает прямой доступ к этим переменным, хотя они имеют тип доступа private.

Можно ли обойтись без внутреннего класса? Можно, например, сделать класс MyCanvas внешним, перенести эти переменные в класс MyCanvas

·  и объявить их как protected. Апплет может получить к ним доступ, поскольку эти два файла (основной класс и MyCanvas. class) находятся в одном каталоге. Тогда в функциях actionPerformed и itemStateChanged присвоение значений этим переменным будет выглядеть так:

p2.n=Integer. parseInt(size. getText());

p2.name=(String)e. getItem();

·  или объявить их как private. Тогда для доступа к этим переменным нужны будут интерфейсные функции (set- и get-), например:

public void setName (String name) { this. name=name; }

public void setN (int n) { this. n=n; }

а в функциях actionPerformed и itemStateChanged присвоение значений этим переменным будет выглядеть так:

p2.setN(Integer. parseInt(size. getText()));

p2.setName((String)e. getItem());

Задание для самостоятельной работы

Изучите самостоятельно классы ItemEvent и ActionEvent, которые используются при передаче параметров в обработчики событий для управляющих элементов (в частности, выясните, к какому классу относятся методы getItem, getSource и getItemSelectable, используемые в примерах этого параграфа, и что они делают).

Обработка событий мыши

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

·  MouseListener (содержит методы mouseClicked, mouseEntered, mouseExited, mousePressed, mouseReleased) и/или

·  MouseMotionListener (содержит методы mouseDragged и mouseMoved),

например

public class mouseEvents extends Applet

implements MouseListener, MouseMotionListener

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

public void init()

{

addMouseListener( this );

addMouseMotionListener( this );

}

Мы рассматриваем апплет, который реагирует на следующие события: нажатие (Up) и отпускание (Down) левой кнопки мыши, простое перемещение мыши (Move) и перемещение мыши при нажатой левой кнопке (Drag). Информация о том, какое событие и с какими координатами произошло, записывается в следующие переменные:

String mouseEvent;

String mouseMoveEvent;

String mouseDragEvent;

String ctrl;

а затем выводится в окно апплета функцией paint.

Любой апплет, который раскрывает какой-либо интерфейс, должен предоставлять код для всех методов этого интерфейса, даже если какой-либо метод и не используется (в этом случае метод просто будет иметь пустое тело), например

public void mouseClicked(MouseEvent e)

{

}

public void mouseReleased(MouseEvent e)

{

int x=e. getPoint().x;

int y=e. getPoint().y;

mouseEvent="mouse Up="+x+","+e. getPoint().y;

repaint();

}

public void mousePressed(MouseEvent e)

{

int x=e. getPoint().x;

int y=e. getPoint().y;

mouseEvent="mouse Down="+x+","+e. getPoint().y;

if (e. isControlDown())

ctrl="Control is down";

repaint();

}

public void mouseEntered(MouseEvent e)

{

}

public void mouseExited(MouseEvent e)

{

}

public void mouseMoved(MouseEvent e)

{

int x=e. getPoint().x;

int y=e. getPoint().y;

mouseMoveEvent="mouse Move="+x+","+y;

repaint();

}

public void mouseDragged(MouseEvent e)

{

int x=e. getPoint().x;

int y=e. getPoint().y;

mouseDragEvent="mouse Drag="+x+","+y;

repaint();

}

public void paint(Graphics g)

{

if (mouseEvent!=null)

{

g. drawString(mouseEvent, 5, 15);

mouseEvent=null;

}

if (mouseMoveEvent!=null)

{

g. drawString(mouseMoveEvent, 5, 35);

mouseMoveEvent=null;

}

if (mouseDragEvent!=null)

{

g. drawString(mouseDragEvent, 5, 55);

mouseDragEvent=null;

}

if (ctrl!=null)

{

g. drawString(ctrl, 5, 75);

ctrl=null;

}

}

Итак, при раскрытии интерфейса слушателя событий мыши требуется переопределить все его абстрактные методы. Однако зачастую требуется обрабатывать только одно из событий мыши. Конечно, задавать пустые версии всех остальных методов не очень приятно. Чтобы сэкономить время и не загромождать код пустыми реализациями методов, в пакете java. awt. event для каждого интерфейса-слушателя включен реализующий его класс, называемый адаптером. Класс-адаптер предоставляет пустые версии всех методов слушателя. Тогда программист должен создать класс, наследующий от класса-адаптера, переопределив только тот метод, который является обработчиком требуемого события. В случае работы с событиями мыши классами-адаптерами являются MouseAdapter и MouseMotionAdapter, соответствующие интерфейсам MouseListener и MouseMotionListener.

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

Создается внутренний класс MouseClickedAdapter, в котором переопределяется только метод mouseClicked.

class mouseClickedAdapter extends MouseAdapter

{

public void mouseClicked(MouseEvent e)

{

int x=e. getPoint().x;

int y=e. getPoint().y;

mouseEvent="mouse click="+x+","+e. getPoint().y;

repaint();

}

}

Метод paint апплета тогда имеет следующий вид:

public void paint(Graphics g)

{

if (mouseEvent!=null)

{

g. drawString(mouseEvent, 5, 15);

mouseEvent=null;

}

}

Наконец, в качестве слушателя событиям мыши в методе init апплета требуется назначить объект класса mouseClickedAdapter.

addMouseListener(new mouseClickedAdapter());

Задание для самостоятельной работы

Изучите самостоятельно класс MouseEvent, который используется при передаче параметров в обработчики событий мыши, и его родительские классы (в частности, выясните, к какому классу относятся методы getPoint и isControlDown, используемые в нашем примере, и что они делают).

Обработка событий клавиатуры

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

·  KeyListener (события keyTyped, keyReleased и keyPressed),

например

public class keyEvents extends Applet implements KeyListener

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

public void init()

{

addKeyListener( this );

}

Мы рассматриваем апплет, который реагирует на следующие события: нажатие (Up) и отпускание (Down) клавиши на клавиатуре. Информация о том, какое событие произошло, записывается в следующие переменные:

String keyDownEvent;

String keyUpEvent;

а затем выводится в окно апплета функцией paint.

Любой апплет, который раскрывает какой-либо интерфейс, должен предоставлять код для всех методов этого интерфейса, даже если какой-либо метод и не используется (в этом случае метод просто будет иметь пустое тело), например

public void keyTyped ( KeyEvent e )

{

}

public void keyReleased ( KeyEvent e )

{

keyUpEvent="Отпущена кнопка "+

e. getKeyText(e. getKeyCode())+

", буква "+e. getKeyChar();

repaint();

}

public void keyPressed ( KeyEvent e )

{

keyDownEvent="Нажата кнопка "+

e. getKeyText(e. getKeyCode())+

", буква "+e. getKeyChar();

repaint();

}

public void paint(Graphics g)

{

if (keyDownEvent!=null)

{

g. drawString(KeyDownEvent, 5, 15);

keyDownEvent=null;

}

if (keyUpEvent!=null)

{

g. drawString(KeyUpEvent, 5, 45);

keyUpEvent=null;

}

}

Задание для самостоятельной работы

Изучите самостоятельно класс KeyEvent, который используется при передаче параметров в обработчики событий мыши (в частности, выясните, что делают методы getKeyText, getKeyCode и getKeyChar, используемые в нашем примере).

Работа с потоками

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

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7