Новый язык программирования
Почему вам нужно изучать новый язык программирования Java?
Если ответить на этот вопрос кратко, то потому, что он специально ориентирован на самые передовые технологии, связанные с сетью Internet. Растущая популярность Internet и, в особенности, серверов WWW, создает для программистов новые возможности для реализации своих способностей. Затратив всего пару-тройку недель на чтение нашей книги, вы сможете проникнуться идеологией Java и, как мы надеемся, сумеете по достоинству оценить возможности этого языка программирования.
В этой главе мы расскажем об основных особенностях Java и библиотеках классов, которые поставляются в составе систем разработки приложений. После этого вы поймете, почему этот язык программирования выглядит весьма привлекательно именно для реализации сетевых проектов в Internet и в корпоративных сетях Intranet.
Первое приложение и первый аплет
Не стремясь быть оригинальными, начнем программирование на Java с составления простейшей программы, которая выводит текстовую строку “Hello, Java!”. Для этого вам сначала нужно установить среду разработки Microsoft Visual J++, запустив программу setup.exe, расположенную в корневом каталоге дистрибутивного компакт-диска.
Процесс установки не вызывает затруднений. Вы просто должны следовать инструкциям, появляющимся на экране. Заметим только, что если у вас уже была установлена система Microsoft Visual C++, то имеет смысл для установки Microsoft Visual J++ использовать тот же каталог, что был использован для установки Microsoft Visual C++. При этом формируется единая среда разработки приложений на языках программирвоания C++ и Java, что очень удобно.
Рисование в окне аплета
В предыдущей главе мы привели простейший пример аплета, который выполняет рисование текстовой строки в своем окне. Теперь мы более подробно расскажем вам о том, что и как может рисовать аплет.
Обработка событий
От аплетов Java было бы немного толку, если бы они не умели обрабатывать информацию, поступающую от мыши и клавиатуры. К счастью, такая обработка предусмотрена и она выполняется достаточно просто.
Когда пользователь выполняет операции с мышью или клавиатурой в окне аплета, возникают события, которые передаются соответствующим методам класса Applet. Переопределяя эти методы, вы можете организовать обработку событий, возникающих от мыши или клавиатуры.
Если вы создавали приложения для операционной системы Microsoft Windows, здесь для вас нет ничего нового - вспомните, как вы обрабатывали сообщение WM_LBUTTONDOWN или WM_CHAR. Когда пользователь выполнял действие с мышью или клавиатурой в окне приложения, функция этого окна получала соответствующее сообщение. Методы класса Applet, обрабатывающие события от мыши и клавиатуры, являются аналогами обработчиков указанных сообщений.
Заметим, что аплеты имеют дело только с левой клавишей мыши. В текущей версии Java вы не можете никаким образом задействовать в аплете правую или среднюю клавишу мыши.
Компоненты в окне аплета
Практически каждое приложение Windows, за исключением самых простейших, имеет такие органы управления, как меню, кнопки, поля редактирования текстовой информации, переключатели с независимой и зависимой фиксацией и списки. Кроме того, приложение Windows может создавать диалоговые панели, содержащие перечисленные выше и другие органы управления.
В окне аплета вы также можете разместить некоторые из перечисленных выше органов управления, а именно:
кнопки;
переключатели с независимой фиксацией;
переключатели с зависимой фиксацией;
статические текстовые поля;
однострочные и многострочные поля редактирования текста;
списки;
полосы просмотра
Самый большой и едва ли приятный сюрприз для вас это то, что при размещении перечисленных органов управления в окне аплета вы не можете задать для них точные координаты и размеры. Размещением занимается система управления внешним видом Layout Manager, которая располагает органы управления по-своему. Вы, однако, можете задавать несколько режимов размещения (последовательное, в ячейках таблицы и так далее), но не координаты или размеры. Это сделано для обеспечения независимости приложений Java от платформ, на которых они выполняются.
Органы управления создаются как объекты классов, порожденных от класса Component (рис. 5.1). Поэтому в дальнейшем мы будем называть органы управления компонентами.
Рис. 5.1. Взаимосвязь классов органов управления в приложениях Java
Класс Button позволяет создавать стандартные кнопки. Если вам нужна нестандартная кнопка (например, графическая кнопка), вы можете создать ее на базе класса Canvas.
Для создания переключателей с независимой или зависимой фиксацией предназначен класс CheckBox.
С помощью класса Label вы можете создавать в окне аплета текстовые строки, например, надписи для других компонент. Эти строки не редактируются пользователем.
Класс List, как нетрудно догадаться из названия, предназначен для создания списков.
С помощью класса Scrollbar вы можете создавать полосы просмотра, которые используются, в частности, могострочными полями редактирования текста.
Класс TextComponent служит базовым для двух других классов - TextField и TextArea. Первый из них предназначен для создания однострочных редакторов текста, второй - для создания многострочных редкаторов текста.
Для того чтобы понять, как компоненты размещаются на поверхности окна аплета системой Layout Manager, рассмотрим другую взаимосвязь классов Java, показанную на рис. 5.2.
Рис. 5.2. Компоненты и контейнеры
Класс Component служит в качестве базового класса для класса Container. Объекты этого класса, которые мы будем называть контейнерами, могут содержать объекты классов Component и Container. Таким образом, внутри контейнеров могут находиться компоненты и другие контейнеры.
Класс Applet, так же как и другие классы, произведенные от класса Container, является контейнером. Это означает, что аплет может содержать в себе компоненты (такие как органы управления) и контейнеры.
Заметим, что класс Applet наследуется от класса Container через класс Panel, в котором определены методы системы Layout Manager. Настраивая соответствующим образом Layout Manager, мы можем менять стратегию размещения компонент внутри окна аплета.
В окне аплета вы можете создать несколько объектов класса Panel (панелей), разделяющих окно на части. Для каждой такой панели можно установить свою стратегию размещения компонент и контейнеров, что позволяет выполнять достаточно сложную компоновку в окне аплета.
Теперь после такого краткого введения в контейнеры и компоненты мы перейдем к описанию методов создания отдельных компонент.
Настройка системы Layout Manager
В предыдущей главе мы рассказали вам о том, как создавать компоненты и размещать их в контейнере. Однако предложенный способ размещения компонент в окне контейнера едва ли можно назвать удобным, так как заранее трудно предугадать, на каком месте окажется тот или иной орган управления.
К счастью, имеются способы, позволяющие контролировать размещение отдельных компонент в окне контейнера. И хотя эти способы не позволяют задавать конкретные координаты и размеры органов управления, использовнные схемы размещения компонент будут правильно работать на любой аппаратной платформе (не забывайте, что Java создавалась как средство разработки приложений, способных выполняться на любой платформе).
В чем трудность создания пользовательского интерфейса для мультиплатформных систем?
В том, что разработчик приложения никогда не знает характеристики устройства отображения, установленные у пользователя. Он, в частности, не может заранее знать разрешение монитора, размер системного шрифта и другие характеристики, необходимые для компоновки диалоговых панелей в терминах абсолютных координат.
Средства пользовательского интерфейса AWT способны динамически измнять размеры компонент, подгоняя их “по месту” в системе пользователя. В результате значительно повышается вероятность того что внешний вид диалоговой панели, в каком она предстанет перед пользователем, будет похож на то, что ожидал разработчик.
Как мы уже говорили в начале предыдущей главы, расположением компонент внутри окна контейнера (например, внутри окна аплета) управляет система Layout Manager. Способ, которым она это делает, весьма непривычен для тех, кто создавал приложения Windows. Выбор этого способа обоснован необходимостью обеспечения совместимости с различными компьютерными платформами.
Работа с панелями
Панели, создаваемые на базе класса Panel, являются мощным средством организации диалогового интерфейса. Так как класс Panel произошел от класса Container, панель может содержать компоненты и другие панели. Для каждой панели можно определить режим размещения компонент, что позволяет создавать достаточно сложный пользовательский интерфейс.
В окне аплета вы можете создать несколько панелей, разделяющих его на части. В свою очередь, пространство, занимаемое панелями, также может быть разделено с использованием одного из описанных выше режимов размещения (рис. 7.1).
Рис. 7.1. Размещение нескольких панелей в окне аплета
Отдельные панели могут содержать в себе такие компоненты, как кнопки, переключатели, списки, текстовые поля и так далее.
Окна и диалоговые панели
До сих пор мы рисовали только в окне аплета или в окнах панелей, расположенных внутри окна аплета. Однако есть и другая возможность - приложения Java, полноценные и аплеты, могут создавать обычные перекрывающиеся окна, такие, например, как окно навигатора. Эти окна могут иметь меню (в отличие от окон аплетов). Пользователь может изменять размер таких окон при помощи мыши, перемещая рамку окна.
В составе библиотеки классов AWT имеется несколько классов, предназначенных для работы с окнами. Это класс Window, который произошел от класса Container, и его дочерние классы - Frame, Dialog и FileDialog (рис. 8.1).
Рис. 8.1. Иерархия классов, предназначенных для создания окон
Окно, созданное на базе класса Frame, больше всего похоже на главное окно обычного приложения Windows. Оно может иметь главное меню, для него можно устанавливать форму курсора. Внутри такого окна можно рисовать. Так как окно класса Frame (так же как и другие окна AWT) произошли от класса Container, вы можете добавлять в них различные компоненты и панели, как мы это делали с окнами аплетов и панелей.
На базе класса Dialog создаются окна диалоговых панелей, очень похожих на обычные диалоговые панели Windows. Такие панели не могут иметь меню и обычно предназначены для запроса какой-либо информации у пользователя.
Класс FileDialog предназначен для создания диалоговых панелей, с помощью которых можно выбирать файлы на локальных дисках компьютера. Так как аплеты не могут работать с файлами, в этой книге мы не будем рассматривать класс FileDialog. Информацию о том, как работать с файлами в приложениях Java, а также сведения об этом классе мы планируем включить в следующий том “Библиотеки системного программиста”, посвященный системе разработки Microsoft Visual J++.
Что же касается класса Window, то непосредственно этот класс редко применяется для создания окон, так как классы Frame, Dialog и FileDialog более удобны и обеспечивают все необходимые возможности.
Аннотация
Книга представляет собой первую часть практического пособия по созданию автономных приложений и аплетов, работающих под управлением навигаторов WWW, на языке программирования Java.
Описаны основные отличия языка программирования Java от С++, среда выполнения приложений Java, приемы работы в интегрированной среде Microsoft Visual J++, основные библиотеки классов Java и методики их использования с иллюстрацией на примерах конкретных приложений. Читатель научится создавать сложные интерактивные аплеты для страниц серверов WWW.
Эта книга будет полезна всем, кто начинает самостоятельно осваивать новый язык программирования Java, и может быть использована в качестве учебного пособия для студентов учебных заведений.
Базовые типы данных
В языке Java определено восемь базовых типов данных, перечисленных ниже:
Тип данных | Размер занимаемой области памяти | Значение по умолчанию | |||
boolean | 8 | false | |||
byte | 8 | 0 | |||
char | 16 | ‘x0’ | |||
short | 16 | 0 | |||
int | 32 | 0 | |||
long | 64 | 0 | |||
float | 32 | 0.0F | |||
double | 64 | 0.0D |
Для каждого базового типа данных отводится конкретный размер памяти, который, как мы говорили в предыдущем разделе, не зависит от платформы, на которой выполняется приложение Java. Фактический размеры памяти, отведенные для хранения переменной, могут отличаться от приведенных выше, например, для хранения переменной типа short может быть зарезервировано слово размером 32 бита. Однако язык Java сделан таким образом, что это никак не повлияет на мобильность приложения. Забегая вперед, скажем, что в языке Java нет указателей, поэтому вы не можете адресоваться к элементам массива чисел по относительному смещению этих элементов в оперативной памяти. Следовательно, точный размер элемента в данном случае не играет никакой роли.
Все базовые типы данных по умолчанию инициализируются, поэтому программисту не нужно об этом беспокоиться. Вы можете также инициализировать переменные базовых типов в программе или при их определении, как это показано ниже:
int nCounter = 0;
int i;
i = 8;
Переменные типа boolean могут находиться только в двух состояниях - true и false, причем эти состояния никаким образом нельзя соотнести с целыми значениями. Вы не можете, как это было в языке С, выполнить преобразование типа boolean, например, к типу int - компилятор выдаст сообщение об ошибке.
Переменная типа byte занимает восемь бит памяти и про нее больше нечего сказать.
Что же касается типа char, то он используется для хранения символов в кодировке Unicode. Эта кодировка позволяет хранить национальные наборы символов, что очень удобно для интернациональных приложений, предназначенных для работы в Internet.
Переменные типа byte, short, int и long являются знаковыми. В языке Java нет беззнаковых переменных, как это было в языке С.
Приложение Java может оперировать числами в формате с плавающей точкой, определенным в спецификации IEEE 754. Тип float позволяет хранить числа с одинарной точностью, а формат double - с двойной.
Переменные базовых типов могут передаваться функциям в качестве параметров только по значению, но не по ссылке. Поэтому следующий фрагмент кода работать не будет:
int x;
void ChangeX(int x)
{
x = 5;
}
. . .
x = 0;
ChangeX(x);
После вызова функции ChangeX содержимое переменной x останется равным нулю.
Проблему можно решить, если вместо базовых переменных использовать объекты встроенных классов, соответствующие базовым переменным. О встроенных классах вы узнаете из следующего раздела.
Библиотека классов java.applet
Как нетрудно догадаться из названия, библиотека классов java.applet инкапсулирует поведение аплетов Java. Когда вы будете создавать свои аплеты, вам будет нужен класс Applet, расположенный в этой библиотеке классов. Дополнительно в библиотеке классов java.applet определены интерфейсы для подключения аплетов к содержащим их документам и классы для проигрывания аудиофрагментов.
Библиотека классов java.awt
Для создания пользовательского интерфейса аплеты Java могут и должны использовать библиотеку классов java.awt. AWT - это сокращение от Abstract Window Toolkit (инструментарий для работы с абстрактными окнами).
Классы, входящие в состав библиотеки java.awt, предоставляют возможность создания пользовательского интерфейса способом, не зависящим от платформы, на которой выполняется аплет Java. Вы можете создавать обычные окна и диалоговые панели, кнопки, переключатели, списки, меню, полосы просмотра, однострочные и многострочные поля для ввода текстовой информации.
Библиотека классов java.awt.image
В среде любой операционной системы работа с графическими изображениями является достаточно сложной задачей. В 14 томе “Библиотеки системного программиста”, который называется “Графический интерфейс GDI в MS Windows” мы детально рассмотрели вопросы, связанные с рисованием графики и обработкой графических файлов в среде операционной системы Microsoft Windows. Если вы будете рисовать графические изображения в среде IBM OS/2 или X-Windows, вам, очевидно, придется использовать другие методики и другой программный интерфейс. Большую сложность также вызывает разбор заголовков графических файлов, так как они могут иметь различный формат и иногда содержат неправильную или противоречивую информацию.
Когда вы программируете на Java, рисование и обработка графических изображений выполняется намного проще, так как вам доступна специально предназначенная для этого библиотека классов java.awt.image. Помимо широкого разнообразия и удобства определенных в ней классов и методов, отметим способность этой библиотеки работать с графическими изображениями в формате GIF. Этот формат широко используется в Internet, так как он позволяет сжимать файлы графических изображений во много раз без потери качества за счет устранения избыточности.
Библиотека классов java.awt.peer
Библиотека классов java.awt.peer служит для подключения компонент AWT (например, кнопок, списков, полей редактирования текстовой информации, переключателей и так далее) к реализациям, зависящим от платформы, в процессе создания этих компонент.
Библиотека классов java.io
В библиотеке классов java.io собраны классы, имеющие отношение к вводу и выводу данных через потоки. Заметим, что с использованием этих классов можно работать не только с потоками байт, но также и с потоками данных других типов, например числами int или текстовыми строками.
Библиотека классов java.net
Язык программирования Java разрабатывался в предположении, что им будут пользоваться для создания сетевых приложений. Поэтому было бы странно, если бы в составе среды разработки приложений Java не поставлялась библиотека классов для работы в сети. Библиотека классов java.net предназначена как раз для этого. Она содержит классы, с помощью которых можно работать с универсальными сетевыми адресами URL, передавать данные с использованием сокетов TCP и UDP, выполнять различные операции с адресами IP. Эта библиотека содержит также классы для выполнения преобразований двоичных данных в текстовый формат, что часто бывает необходимо.
В качестве примера приложения, составленного на языке программирования Java и ориентированного на работу в сети Internet, можно привести игру Java Color Lines (рис. 1.3).
Рис. 1.3. Сетевая игра Java Color Lines, расположенная на сервере http://spektr.orc.ru
Это сетевая версия извстной игры Lines, которая выполнена в виде нескольких аплетов, взаимодействующих между собой и между сервером WWW с адресом http://spektr.orc.ru, на котором они расположены. Так как список имен игроков и достигнутых ими результатов хранится на сервере, вы можете поучаствовать в мировом турнире, сразившись с игроками из разных стран.
В следующем томе “Библиотеки системного программиста”, посвященном Java, мы расскажем о том, как организовать взаимодействие между аплетами и сервером WWW.
Библиотека классов java.util
Библиотека классов java.util очень полезна при составлении приложений, так как в ней имеются классы для создания таких структур, как динамические массивы, стеки и словари. Есть классы для работы с генератором псевдослучайных чисел, для разбора строк на составляющие элементы (токены), для работы с календарной датой и временем.
Библиотеки классов Java
Если предоставить в распоряжение программиста только язык программирования и не снабдить его набором готовых модулей, предназначенных для решения самых распространенных задач, ему придется отвлекаться на множество мелких деталей. Обычно все профессиональные системы разработки приложений содержат в своем составе набор стандартных библиотечных функций или библиотеки классов, таких как Microsoft MFC или Borland OWL. В комплекте со всеми средствами разработки Java поставляются достаточно развитые библиотеки классов, значительно упрощающие программирование. В этом разделе мы кратко расскажем о составе и назначении библиотек классов Java.
Благодарности
В работе над книгой нам помогали сотрудники фирмы Interactive Products Inc. Максим Синев и Сергей Ноженко, у которых мы консультировались по различным вопросам.
Мы признательны генеральному директору АО “ДиалогНаука” Антимонову Сергею Григорьевичу и его заместителю Лященко Юрию Павловичу за возможность размещения информации о наших книгах на сервере Web по адресу http://www.dials.ccas.ru/frolov, а также за возможность доступа к сети Internet через сервер АО “ДиалогНаука”.
Мы также благодарим корректора Кустова В. С. и сотрудников издательского отдела АО “Диалог-МИФИ” Голубева О. А., Голубева А. О., Дмитриеву Н. В., Виноградову Е. К., Кузьминову О. А.
Добавление компонент в панели
Для добавления компонент в панель вы должны указать, для какой панели вызывается метод add, например:
Botton btn1;
Botton btn2;
btn1 = new Button();
btn2 = new Button();
pBottomPanel.add(btn1);
pBottomPanel.add(btn2);
Добавление панелей
Создав панели, вы можете добавить их в окно аплета, вызвав метод add, как это показано ниже:
add(pTopPanel);
add(pBottomPanel);
Заметим, что вы можете добавлять панели в панели, указывая, для какой панели нужно вызывать метод add:
Panel pLeft;
Panel pRight;
pLeft = new Panel();
pRight = new Panel();
pTopPanel.setLayout(new GridLayout(1, 2));
pTopPanel.add(pLeft);
pTopPanel.add(pRight);
Здесь мы создали две панели pLeft и pRight, которые по нашему замыслу должны разделить пространство панели pTopPanel на две части по вертикали. Для обеспечения вертикального размещения панелей pLeft и pRight в панели pTopPanel мы вызвали для панели pTopPanel метод setLayout. При этом мы указали, что компоненты, добавляемые в эту панель, должны размещаться в таблице, состоящей из односй строки и двух столбцов.
Затем панели pLeft и pRight были добавлены в панель pTopPanel методом add.
Другие встроенные классы
Среди других встроенных классов отметим класс Math, предназначенный для выполнения математических операций, таких как взятие синуса, косинуса и тангенса.
Предусмотрены также классы для выполнения запуска процессов и задач, управления системой безопасности, а также для решения прочих системных задач.
Библиотека встроенных классов содержит очень важные классы для работы с исключениями. Эти классы нужны для обработки ошибочных ситуаций, которые могут возникнуть (и возникают!) при работе приложений или аплетов Java.
Файл HelloAp.java
Исходный текст аплета HelloAp начинается с двух строк, подключающих оператором import библиотеки классов:
import java.applet.*;
import java.awt.*;
Оператор import должен располагаться в файле исходного текста перед другими операторами (за исключением операторов комментария). В качестве параметра оператору import передается имя подключаемого класса из библиотеки классов. Если же необходимо подключить все классы данной библиотеки (как в нашем случае), вместо имени класса указывается символ“*”.
Мы уже перечисляли библиотеки классов Java. Напомним, что библиотека java.applet содержит классы, необходимые для создания аплетов, то есть разновидности приложений Java, встраиваемых в документы HTML и работающих под управлением навигатора Internet. С помощью классов библиотеки java.awt аплет может выполнять в своем окне рисование различных изображений или текста, причем данный метод рисования не зависит от платформы, на которой работает аплет.
Далее в исходном тексте аплета определяется класс типа public с именем HelloAp, которое должно обязательно совпадать с именем файла, содержащего исходный текст этого класса:
public class HelloAp extends Applet
{
. . .
}
Определенный нами класс HelloAp с помощью ключевого слова extends наследуется от класса Applet. При этом методам класса HelloAp становятся доступными все методы и данные класса, за исключением определенных как private. Класс Applet определен в библиотеке классов java.applet, которую мы подключили оператором import.
Создавая файл HelloAp.java, система Java Applet Wizard определили в классе HelloAp конструктор и несколько методов, заменив некоторые методы базового класса Applet.
Файл HelloApp.html
Файл HelloApp.html автоматически создается системой Java Applet Wizard, если это было указано во второй диалоговой панели, задающей параметры нового проекта.
Нас интересует в этом файле оператор <APPLET>, который используется в паре с оператором </APPLET> и предназначен для встраивания окна аплета в документ HTML.
Вот как выглядит фрагмент документа HTML, созданного для нашего проекта, в котором встраивается аплет:
<applet
code=HelloAp.class
id=HelloAp
width=320
height=240 >
</applet>
Рассмотрим параметры оператора <APPLET>, указанные в этом фрагменте кода, а также некоторые другие.
Параметр | Описание | ||
ALIGN | Выравнивание окна аплета относительно окружающего его текста. Возможны следующие значения:
LEFT выравнивание влево относительно окружающего текста; CENTER центрирование; RIGHT выравнивание вправо относительно окружающего текста; TOP выравнивание по верхней границе; MIDDLE центрирование по вертикали; BOTTOM выравнивание по нижней границе | ||
ALT | С помощью этого параметра можно задать текст, который будет отображаться в окне аплета в том случае, если навигатор не может работать с аплетами Java | ||
CODE | Имя двоичного файла, содержащего код аплета. По умолчанию путь к этому файлу указывается относительно каталога с файлом HTML, в который встроен аплет. Такое поведение может быть изменено параметром CODEBASE | ||
CODEBASE | Базовый адрес URL аплета, то есть путь к каталогу, содержащему аплет | ||
HEIGHT | Начальная ширина окна аплета в пикселах | ||
WIDTH | Начальная высота окна аплета в пикселах | ||
HSPACE | Зазор слева и справа от окна аплета | ||
VSPACE | Зазор сверху и снизу от окна аплета | ||
NAME | Идентификатор аплета, который может быть использован другими аплетами, расположенными в одном и том же документе HTML | ||
TITLE | Строка заголовка |
Дополнительно между операторами <APPLET> и </APPLET> вы можете задать параметры аплета. Для этого используется оператор <PARAM>, который мы рассмотрим позже.
Внешний вид окна навигатора, в котором отображается созданный документ HTML с аплетом, показан на рис. 2.15.
Рис. 2.15. Окно аплета в документе HTML
Обратите внимание, что границы окна аплета никак не выделяются, а цвет его фона совпадает с цветом фона документа HTML. В следующей главе мы научим вас изменять цвет фона окна аплета и текста, отображаемого в этом окне.
В нижней части окна под разделительной линией находится ссылка на исходный текст аплета:
<a href="HelloAp.java">The source.</a>
Вы можете использовать эту ссылку для просмотра содержимого файла HelloAp.java.
Интерфейсы
Интерфейсы создаются при помощи ключевого слова interface таким же образом, что и классы. Однако в отличие от последних, интерфейсы являются аналогом абстрактных базовых классов без полей данных и предназначены только для определений набора методов для решения каких-либо задач, например, добавления компонент в контейнеры, организации списков, сортировки и так далее.
Вы можете создать свой класс на базе другого класса, указав при этом с помощью ключевого слова implements, что он реализует тот или иной интерфейс. При этом наряду с методами базового класса в созданном таким образом классе будут доступны методы, определенные в интерфейсе.
Исходные файлы аплета HelloAp
Как мы уже говорили, в результате работы системы Java Applet Wizard созданы файлы HelloAp.java и HelloAp.html. Рассмотрим их по отдельности.
Исходные файлы приложения Painter
В листинге 3.1 мы привели исходный текст аплета Painter.
Листинг 3.1. Файл Painter\Painter.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 Painter extends Applet
{
// -------------------------------------------------------
// Painter
// Конструктор не используется
// -------------------------------------------------------
public Painter()
{
}
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: Painter\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";
}
// -------------------------------------------------------
// init
// Вызывается во время инициализации аплета
// -------------------------------------------------------
public void init()
{
// Для того чтобы размеры окна аплета можно было
// задавать в документе HTML, закрываем следующую
// строку символом комментария
// resize(320, 240);
}
// -------------------------------------------------------
// destroy
// Метод destroy не используется
// -------------------------------------------------------
public void destroy()
{
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
{
// Определяем текущие размеры окна аплета
Dimension dimAppWndDimension = size();
// Эта строка будет удалена из окна аплета
// методом clearRect
g.drawString("Невидимая строка", 10, 20);
// Стираем содержимое окна аплета. Цвет окна
// становится таким же, как и цвет фона
// окна навигатора
g.clearRect(0, 0,
dimAppWndDimension.width - 1,
dimAppWndDimension.height - 1);
// Выбираем в контекст отображения желтый цвет
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);
// Пишем строку в верхнем левом углу окна аплета
g.drawString("Привет из аплета!", 10, 20);
// Рисуем в цикле пять горизонтальных линий
for(int i = 0; i < 5; i++)
{
g.drawLine(10, 30 + (i * 10), 200, 30 + (i * 10));
}
// Копируем область окна, занятую
// нарисованными линиями
g.copyArea(10, 30, 200, 50, 220, 0);
// Выбираем в контекст отображения белый цвет
g.setColor(Color.white);
// Закрашиваем белвым цветом нижнюю часть окна
g.fillRect(1, 80,
dimAppWndDimension.width - 2,
dimAppWndDimension.height - 81);
// Выбираем в контекст отображения черный цвет
g.setColor(Color.black);
// Рисуем два трехмерных прямоугольника
g.draw3DRect(10, 100, 100, 20, true);
g.draw3DRect(120, 100, 100, 20, false);
// Выбираем в контекст отображения красный цвет
g.setColor(Color.red);
// Рисуем рамку, в которую будет вписан сегмент
g.drawRect(10, 140, 200, 100);
g.drawLine(10, 190, 210, 190);
g.drawLine(110, 140, 110, 240);
// Выбираем в контекст отображения черный цвет
g.setColor(Color.black);
// Рисуем сегмент
g.drawArc(10, 140, 200, 100, -25, 320);
// Создаем многоугольник
Polygon p = new Polygon();
// Добавляем в многоугольник несколько вершин
p.addPoint(270, 239);
p.addPoint(350, 230);
p.addPoint(360, 180);
p.addPoint(390, 160);
p.addPoint(340, 130);
p.addPoint(270, 239);
// Рисуем многоугольник
g.drawPolygon(p);
// Рисуем прямоугольник с закругленными углами
g.drawRoundRect(10, 250, 200, 100, 60, 40);
// Выбираем в контекст отображения красный цвет
g.setColor(Color.red);
// Задаем область ограничения вывода
g.clipRect(260, 250, 200, 100);
// Рисуем круг, пересекающий область ограничения
g.fillOval(300, 200, 170, 170);
}
// -------------------------------------------------------
// start
// Метод start не используется
// -------------------------------------------------------
public void start()
{
}
// -------------------------------------------------------
// stop
// Метод stop не используется
// -------------------------------------------------------
public void stop()
{
}
}
Листинг 3. 2 содержит исходный текст документа HTML, в который встроен данный аплет.
Листинг 3.2. Файл Painter\Painter.html
<html>
<head>
<title>Painter</title>
</head>
<body>
<hr>
<applet
code=Painter.class
id=Painter
width=500
height=400>
</applet>
<hr>
<a href="Painter.java">The source.</a>
</body>
</html>
Мы внесли небольшие изменения в файл Painter.html, подготовленный системой Java Applet Wizard. Эти изменения заключаются в увеличении размеров окна аплета, задаваемых параметрами WIDTH и HEIGHT оператора <APPLET>.
Исходные тексты приложения
Файл исходного текста приложения MouseClick представлен в листинге 4.1.
Листинг 4.1. Файл MouseClick\MouseClick.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 MouseClick extends Applet
{
// Текущие координаты курсора при нажатии на
// кнопку мыши
Dimension dimMouseCursor;
// Временная переменная для хранения события
Event ev;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: MouseClick\r\n" +
"E-mail: frolov@glas.apc.org" +
"WWW: http://www.glasnet.ru/~frolov" +
"Author: Alexandr Frolov\r\n" +
"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);
Исходный текст аплета LineDraw приведен в листинге 4.3.
Листинг 4.3. Файл LineDraw\LineDraw.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.*;
// Добавляем для класса Vector
import java.util.*;
public class LineDraw extends Applet
{
// Координаты курсора при нажатии кнопки мыши
Dimension dmDown;
// Координаты курсора при отжатии кнопки мыши
Dimension dmUp;
// Предыдущие координаты конца линии
Dimension dmPrev;
// Признак включения режима рисования
boolean bDrawing;
// Массив координат линий
Vector lines;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: LineDraw\r\n" +
"E-mail: frolov@glas.apc.org" +
"WWW: http://www.glasnet.ru/~frolov" +
"Author: Alexandr Frolov\r\n" +
"Created with Microsoft Visual J++ Version 1.0";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Сброс признака рисования
bDrawing = false;
// Создание массива для хранения координат линий
lines = new Vector();
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
Файл исходных текстов приложения ListBox приведен в листинге 5.7.
Листинг 5.7. Файл ListBox\ListBox.java
// =========================================================
// Списки типа List Box
//
// (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 ListBox extends Applet
{
// Создаем ссылки на объекты класса List
List chBackgroundColor;
List chForegroundColor;
// Строки для хранения названий выбираемого цвета
String sSelBackground = new String("Yellow");
String sSelForeground = new String("Black");
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: ListBox\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем списки для выбора цвета фона и
// цвета изображения
chBackgroundColor = new List(6, false);
chForegroundColor = new List(4, false);
// Добавляем списки в окно аплета
add(chBackgroundColor);
add(chForegroundColor);
// Заполняем список цвета фона
chBackgroundColor.addItem("Yellow");
chBackgroundColor.addItem("Green");
chBackgroundColor.addItem("White");
chBackgroundColor.addItem("Black");
Исходный текст приложения TextLabel приведен в листинге 5.9.
Листинг 5.9. Файл TextLabel\TextLabel.java
// =========================================================
// Работа с компонентами Label
//
// (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 TextLabel extends Applet
{
// Создаем ссылку на объекты типа Label
Label lbTextLabel;
// Создаем три ссылки на объекты типа Button
Button btnLeft;
Button btnCenter;
Button btnRight;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: TextLabel\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем компоненту Label
lbTextLabel = new Label("Выберите выравнивание");
// Создаем три кнопки
btnLeft = new Button("Влево");
btnCenter = new Button("Центровка");
btnRight = new Button("Вправо");
// Добавляем три кнопки
add(btnLeft);
add(btnCenter);
add(btnRight);
// Добавляем компоненту Label
add(lbTextLabel);
// Устанавливаем цвет фона
setBackground(Color.yellow);
}
// -------------------------------------------------------
Исходные тексты приложения TxtField представлены в листинге 5.11.
Листинг 5.11. Файл TxtField\TxtField.java
// =========================================================
// Однострочное текстовое поле класса TextField
//
// (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 TxtField extends Applet
{
// Создаем ссылку на объекты типа TextField
TextField txt;
// Создаем ссылку на объекты типа Button
Button btnGetText;
// Строка для хранения введенных данных
String str;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: TxtField\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем редактируемое однострочное текстовое поле
txt = new TextField("Введите строку текста", 35);
// Создаем кнопку, с помощью которой можно получить
// содержимое текстового поля
btnGetText = new Button("Получить строку");
// Добавляем текстовое поле в окно аплете
add(txt);
// Добавляем кнопку в окно аплете
add(btnGetText);
// Получаем и сохраняем текущий текст,
// установленный в поле
str = txt.getText();
Исходный текст приложения приведен в листинге 5.13.
Листинг 5.13. Файл TextEdit\TextEdit.java
// =========================================================
// Многострочное текстовое поле класса TextArea
//
// (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 TextEdit extends Applet
{
// Создаем ссылку на объект типа TextArea
TextArea txt;
// Создаем ссылку на объекты типа Button
Button btnGetText;
Button btnGetSelectedText;
String str;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: TextEdit\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем редактируемое многострочное текстовое поле
txt = new TextArea("Введите строку текста", 5, 35);
// Создаем кнопку, с помощью которой можно получить
// полное содержимое текстового поля
btnGetText = new Button("Получить все");
// Создаем кнопку, с помощью которой можно получить
// содержимое выделенной области текстового поля
btnGetSelectedText = new Button("Получить выделенное");
// Добавляем текстовое поле в окно аплете
add(txt);
Исходный текст аплета Grid приведен в листинге 6.1.
Листинг 6.1. Файл Grid\Grid.java
// =========================================================
// Режим компоновки GridLayout
//
// (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 Grid extends Applet
{
// Создаем ссылки на объекты типа Button
Button btn1;
Button btn2;
Button btn3;
Button btn4;
Button btn5;
Button btn6;
Button btn7;
Button btn8;
// Строка для записи названия нажатой кнопки
String sTextLabel;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: Grid\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.1";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Устанавливаем желтый цвет фона
setBackground(Color.yellow);
// Создаем кнопки
btn1 = new Button("Button 1");
btn2 = new Button("Button 2");
btn3 = new Button("Button 3");
btn4 = new Button("Button 4");
btn5 = new Button("Button 5");
btn6 = new Button("Button 6");
btn7 = new Button("Button 7");
btn8 = new Button("Button 8");
// Устанавливаем режим GridLayout
Исходный текст приложения Border приведен в листинге 6.3.
Листинг 6.3. Файл Border\Border.java
// =========================================================
// Режим компоновки BorderLayout
//
// (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 Border extends Applet
{
// Создаем ссылки на объекты типа Button
Button btn1;
Button btn2;
Button btn3;
Button btn4;
Button btn5;
// Строка для записи названия нажатой кнопки
String sTextLabel;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: Grid\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.1";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Устанавливаем желтый цвет фона
setBackground(Color.yellow);
// Создаем кнопки
btn1 = new Button("Button North");
btn2 = new Button("Button East");
btn3 = new Button("Button West");
btn4 = new Button("Button South");
btn5 = new Button("Button Center");
// Устанавливаем режим GridLayout
setLayout(new BorderLayout());
// Добавляем кнопки в контейнер
add("North", btn1);
add("East", btn2);
Файл исходного текста приложения PanelDemo представлен в листинге7.1.
Листинг 7.1. Файл PanelDemo\PanelDemo.java
// =========================================================
// Работа с панелями класса Panel
//
// (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 PanelDemo extends Applet
{
// Панель для размещения блокнота
Panel pCardPanel;
// Панель для размещения кнопок управления блокнотом
Panel pButtonPanel;
// Создаем ссылки на объекты типа Button
Button btn1;
Button btn2;
Button btn3;
Button btn4;
Button btn5;
Button btnNext;
Button btnPrev;
// Строка для записи названия нажатой кнопки
String sTextLabel;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: Grid\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.1";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Устанавливаем желтый цвет фона
setBackground(Color.yellow);
// Создаем в окне аплета две панели, разделяющие
// окно по горизонтали. В верхней панели будет
// находиться блокнот,
// в нижней - кнопки управления блокнотом
setLayout(new GridLayout(2, 1));
// Создаем кнопки блокнота
Исходный текст приложения Notebook приведен в листинге 7.3.
Листинг 7.3. Файл Notebook\Notebook.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 Notebook extends Applet
{
// Панель для размещения блокнота
Panel pCardPanel;
// Панель для размещения кнопок управления блокнотом
Panel pButtonPanel;
// Панель для рисования
Panel pDraw;
// Панели отдельных страниц
Panel pBackgroundColor; // страница выбора цвета фона
Panel pForegroundColor; // страница выбора цвета
// изображения
Panel pFont; // страница выбора шрифта
// Кнопки выбора сраниц блокнота
Button btnNext; // следующая
Button btnPrev; // предыдущая
Button btnBackgroundColor; // фон
Button btnForegroundColor; // изображение
Button btnFont; // шрифт
// Создаем ссылки на объекты класса Choice
Choice chBackgroundColor; // список цветов фона
Choice chForegroundColor; // список цветов изображения
Choice chFont; // список шрифтов
// Текстовые метки списков
Label tBackgroundColor; // метка списка цветов фона
Label tForegroundColor; // метка списка цветов
// изображения
Label tFont; // метка списка шрифтов
// Строка для хранения название выбранного шрифта
String sFontName;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
Файл исходных текстов приложения приведен в листинге 7.5.
Листинг 7.5. Файл Panel2\Panel2.java
// =========================================================
// Работа с панелями класса Panel
// Наследование от класса Panel
//
// (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.*;
// =========================================================
// Класс Panel2
// Это наш аплет
// =========================================================
public class Panel2 extends Applet
{
// Первая панель
FirstPanel pPanel1;
// Вторая панель
SecondPanel pPanel2;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: Panel2\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем в окне аплета две панели, разделяющие
// окно по горизонтали
setLayout(new GridLayout(2, 1));
// Создаем первую панель
pPanel1 = new FirstPanel();
// Добавляем первую панель в окно аплета
add(pPanel1);
// Создаем вторую панель
pPanel2 = new SecondPanel();
// Добавляем вторую панель
add(pPanel2);
// Устанавливаем желтый цвет фона для первой панели
pPanel1.setBackground(Color.yellow);
Исходный текст приложения FrameWnd приведен в листинге 8.1.
Листинг 8.1. Файл FrameWnd\FrameWnd.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.*;
// =========================================================
// Класс FrameWnd
// Это наш аплет
// =========================================================
public class FrameWnd extends Applet
{
// Окно, которое будет возникать из аплета
MainFrameWnd fMainFrame;
// Кнопка для отображения окна fMainFrame
Button btnShowFrame;
// Кнопка для удаления окна fMainFrame
Button btnHideFrame;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: FrameWnd\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем новое окно на базе класса MainFrameWnd
fMainFrame = new MainFrameWnd("Main Frame Window");
// Создаем кнопку для отображения этого окна
btnShowFrame = new Button("Show Frame Window");
// Добавляем кнопку в окно аплета
add(btnShowFrame);
// Создаем кнопку для удаления окна fMainFrame
Исходные тексты приложения ButtonPress
Исходный текст приложения ButtonPress приведен в листинге 5.1.
Листинг 5.1. Файл ButtonPress\ButtonPress.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 ButtonPress extends Applet
{
// Создаем четыре ссылки на объекты типа Button
Button btn1;
Button btn2;
Button btn3;
Button btn4;
// Строка для записи названия нажатой кнопки
String sTextLabel;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающий строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: ButtonPress\r\n" +
"E-mail: frolov@glas.apc.org" +
"WWW: http://www.glasnet.ru/~frolov" +
"Author: Alexandr Frolov\r\n" +
"Created with Microsoft Visual J++ Version 1.0";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем четыре кнопки
btn1 = new Button("Button 1");
btn2 = new Button("Button 2");
btn3 = new Button("Button 3");
btn4 = new Button("Button 4");
// Добавляем кнопки в контейнер, которым является
// окно аплета
add(btn1);
add(btn2);
add(btn3);
add(btn4);
// Название кнопки, нажатой в последний раз
sTextLabel = new String("");
}
// -------------------------------------------------------
// action
// Метод вызывается, когда пользователь выполняет
// действие над компонентами
// -------------------------------------------------------
public boolean action(Event evt, Object obj)
{
// Ссылка на кнопку, от которой пришло сообщение
Button btn;
// Проверяем, что событие вызвано кнопкой, а не
// другим компонентом
if(evt.target instanceof Button)
{
// Получам ссылку на кнопку, вызвавшую событие
btn = (Button)evt.target;
// Получаем название кнопки
sTextLabel = btn.getLabel();
// Выполняем ветвление по кнопкам. Для каждой кнопки
// записываем ее название
// в строку состояния навигатора
if(evt.target.equals(btn1))
{
showStatus(
"Button 1 (\"" + sTextLabel + "\") pressed");
}
else if(evt.target.equals(btn2))
{
showStatus(
"Button 2 (\"" + sTextLabel + "\") pressed");
}
else if(evt.target.equals(btn3))
{
showStatus(
"Button 3 (\"" + sTextLabel + "\") pressed");
}
else if(evt.target.equals(btn4))
{
showStatus(
"Button 4 (\"" + sTextLabel + "\") pressed");
}
// Если событие возникло от неизвестной кнопки,
// мы его не обрабатываем
else
{
return false;
}
// Перерисовываем окно аплета
repaint();
// возвращаем признак того, что мы обработали событие
return true;
}
// Если событие вызвано не кнопкой,
// мы его не обрабатываем
return false;
}
// -------------------------------------------------------
// 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);
// Рисуем название нажатой кнопки
g.drawString("Button (\"" + sTextLabel + "\") pressed",
10, 70);
}
}
Исходный текст документа HTML, созданный для аплета ButtonPress, представлен в листинге 5.2.
Листинг 5.2. Файл ButtonPress\ButtonPress.html
<html>
<head>
<title>ButtonPress</title>
</head>
<body>
<hr>
<applet
code=ButtonPress.class
id=ButtonPress
width=320
height=240 >
</applet>
<hr>
<a href="ButtonPress.java">The source.</a>
</body>
</html>
Исходные тексты приложения CheckBoxes
Файл исходного текста приложения CheckBoxes представлен в листинге 5.3.
Листинг 5.3. Файл CheckBoxes\CheckBoxes.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 CheckBoxes extends Applet
{
// Создаем три ссылки на объекты типа Checkbox
Checkbox chbox1;
Checkbox chbox2;
Checkbox chbox3;
// Создаем ссылку на объект типа CheckboxGroup
CheckboxGroup grModeGroup;
// Создаем четыре ссылки на объекты типа Checkbox
Checkbox rdbox1;
Checkbox rdbox2;
Checkbox rdbox3;
Checkbox rdbox4;
// Создаем ссылку на объект типа Button
Button btnGet;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: CheckBoxes\r\n" +
"WWW: http://www.glasnet.ru/~frolov" +
"E-mail: frolov@glas.apc.org" +
"Author: Alexandr Frolov\r\n" +
"Created with Microsoft Visual J++ Version 1.0";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Устанавливаем желтый цвет фона
setBackground(Color.yellow);
// Создаем три переключателя с независимой фиксацией
chbox1 = new Checkbox("Switch 1");
chbox2 = new Checkbox("Switch 2");
chbox3 = new Checkbox("Switch 3");
// Создаем группу переключателей с зависимой фиксацией
grModeGroup = new CheckboxGroup();
// Создаем четыре переключателя с зависимой фиксацией,
// принадлежащие группе grModeGroup
rdbox1 = new Checkbox("Mode 1",grModeGroup, true);
rdbox2 = new Checkbox("Mode 2",grModeGroup, false);
rdbox3 = new Checkbox("Mode 3",grModeGroup, false);
rdbox4 = new Checkbox("Mode 4",grModeGroup, false);
// Создаем кнопку, предназначенную для определения
// текущего состояния переключателей
btnGet = new Button("Get CheckBoxes state");
// Добавляем в окно аплета четыре переключателя
// с зависимой фиксацией
add(rdbox1);
add(rdbox2);
add(rdbox3);
add(rdbox4);
// Добавляем в окно аплета три переключателя
// с независимой фиксацией
add(chbox1);
add(chbox2);
add(chbox3);
// Добавляем в окно аплета кнопку
add(btnGet);
}
// -------------------------------------------------------
// action
// Метод вызывается, когда пользователь выполняет
// действие над компонентами
// -------------------------------------------------------
public boolean action(Event evt, Object obj)
{
// Проверяем, что событие вызвано кнопкой, а не
// другим компонентом
if(evt.target instanceof Button)
{
// Выполняем ветвление по кнопкам.
if(evt.target.equals(btnGet))
{
showStatus("Button 1 pressed");
}
// Если событие возникло от неизвестной кнопки,
// мы его не обрабатываем
else
{
return false;
}
// Перерисовываем окно аплета
repaint();
// возвращаем признак того, что мы обработали событие
return true;
}
// Если событие вызвано не кнопкой,
// мы его не обрабатываем
return false;
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
{
// Определяем текущие размеры окна аплета
Dimension dimAppWndDimension = size();
// Выбираем в контекст отображения черный цвет
g.setColor(Color.black);
// Рисуем рамку вокруг окна аплета
g.drawRect(0, 0,
dimAppWndDimension.width - 1,
dimAppWndDimension.height - 1);
// Строка для записи списка
// состояния переключателей
String s = new String("> ");
// Проверяем переключатели с независимой фиксацией
if(chbox1.getState())
s = s + chbox1.getLabel() + ", ";
if(chbox2.getState())
s = s + chbox2.getLabel() + ", ";
if(chbox3.getState())
s = s + chbox3.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();
// Рисуем строку состояния переключателей
g.drawString(s, 10, 150);
}
}
В листинге 5. 4 вы найдете исходный текст документа HTML, который был создан системой Java Applet Wizard для нашего аплета.
Листинг 5.4. Файл CheckBoxes\CheckBoxes.html
<html>
<head>
<title>CheckBoxes</title>
</head>
<body>
<hr>
<applet
code=CheckBoxes.class
id=CheckBoxes
width=320
height=240 >
</applet>
<hr>
<a href="CheckBoxes.java">The source.</a>
</body>
</html>
Исходные тексты приложения ChoiceList
Исходный текст приложения ChoiceList вы найдете в листинге 5.5.
Листинг 5.5. Файл ChoiceList\ChoiceList.java
// =========================================================
// Списки типа Drop Down
//
// (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 ChoiceList extends Applet
{
// Создаем ссылки на объекты класса Choice
Choice chBackgroundColor;
Choice chForegroundColor;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: ChoiceList\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";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Создаем списки для выбора цвета фона и
// цвета изображения
chBackgroundColor = new Choice();
chForegroundColor = new Choice();
// Добавляем списки в окно аплета
add(chBackgroundColor);
add(chForegroundColor);
// Заполняем список цвета фона
chBackgroundColor.addItem("Yellow");
chBackgroundColor.addItem("Green");
chBackgroundColor.addItem("White");
// Заполняем список цвета изображения
chForegroundColor.addItem("Black");
chForegroundColor.addItem("Red");
chForegroundColor.addItem("Blue");
// Устанавливаем цвет фона
setBackground(Color.yellow);
// Устанавливаем цвет изображения
setForeground(Color.black);
}
// -------------------------------------------------------
// action
// Метод вызывается, когда пользователь выполняет
// действие над компонентами
// -------------------------------------------------------
public boolean action(Event evt, Object obj)
{
// Переменная для хранения ссылки на список,
// вызвавший событие
Choice ch;
// Получаем ссылку на список
ch = (Choice)evt.target;
// Проверяем, что событие вызвано списком, а не
// другим компонентом
if(evt.target instanceof Choice)
{
// Выполняем ветвление по спискам
// Список цвета фона
if(evt.target.equals(chBackgroundColor))
{
// Получаем номер текущего элемента списка
// и устанавливаем соответствующий
// цвет фона
if(ch.getSelectedIndex() == 0)
setBackground(Color.yellow);
else if(ch.getSelectedIndex() == 1)
setBackground(Color.green);
else if(ch.getSelectedIndex() == 2)
setBackground(Color.white);
}
// Список цвета изображения
else if(evt.target.equals(chForegroundColor))
{
// Получаем номер текущего элемента списка
// и устанавливаем соответствующий
// цвет изображения
if(ch.getSelectedIndex() == 0)
setForeground(Color.black);
else if(ch.getSelectedIndex() == 1)
setForeground(Color.red);
else if(ch.getSelectedIndex() == 2)
setForeground(Color.blue);
}
// Если событие возникло от неизвестного списка,
// мы его не обрабатываем
else
{
return false;
}
// Перерисовываем окно аплета
repaint();
// возвращаем признак того, что мы обработали событие
return true;
}
// Если событие вызвано не кнопкой,
// мы его не обрабатываем
return false;
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
{
// Определяем текущие размеры окна аплета
Dimension dimAppWndDimension = size();
// Рисуем рамку вокруг окна аплета
g.drawRect(0, 0,
dimAppWndDimension.width - 1,
dimAppWndDimension.height - 1);
// Рисуем строку
g.drawString("Смотри на цвет фона и текста!", 10, 50);
}
}
Исходный текст документа HTML, созданного для нашего аплета, приведен в листинге 5.6.
Листинг 5.6. Файл ChoiceList\ChoiceList.html
<html>
<head>
<title>ChoiceList</title>
</head>
<body>
<hr>
<applet
code=ChoiceList.class
id=ChoiceList
width=320
height=240 >
</applet>
<hr>
<a href="ChoiceList.java">The source.</a>
</body>
</html>
Исходные тексты приложения KeyCode
Файл исходного текста приложения KeyCode приведен в листинге 4.5.
Листинг 4.5. Файл KeyCode\KeyCode.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 KeyCode extends Applet
{
// Высота символов текущего шрифта
int yHeight;
// Текущие размеры окна аплета
Dimension dimAppWndDimension;
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: KeyCode\r\n" +
"Author: Alexandr Frolov\r\n" +
"WWW: http://www.glasnet.ru/~frolov" +
"Author: Alexandr Frolov\r\n" +
"Created with Microsoft Visual J++ Version 1.0";
}
// -------------------------------------------------------
// init
// Метод, получающий управление при инициализации аплета
// -------------------------------------------------------
public void init()
{
// Получаем контекст отображения
Graphics g = getGraphics();
// Определяем метрики текущего шрифта
FontMetrics fm = g.getFontMetrics();
// Сохраняем полную высоту символов шрифта
yHeight = fm.getHeight();
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
{
// Определяем текущие размеры окна аплета
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);
}
// -------------------------------------------------------
// keyDown
// Вызывается, когда пользователь нажимает на клавишу
// -------------------------------------------------------
public boolean keyDown(Event evt, int nKey)
{
// Массив для преобразования кода символа в сивол
char[] chKey;
// Временная строка
String s;
// Создаем массив из одного элемента
chKey = new char[1];
// Записыаем в него код нажатой клавиши
chKey[0] = (char)nKey;
// Преобразуем в строку
s = new String(chKey);
// Получаем контекст отображения
Graphics g = getGraphics();
// Выбираем черный цвет для рисования
g.setColor(Color.black);
// Рисуем символ, соответствующий нажатой клавише
g.drawString(s + " ", 10, 10);
// Рисуем код клавиши
g.drawString(
" -> key: " + evt.key, 20, 10);
// Рисуем код модификации
g.drawString(" mod: " + evt.modifiers, 100, 10);
return true;
}
// -------------------------------------------------------
// keyUp
// Вызывается, когда пользователь отпускает клавишу
// -------------------------------------------------------
public boolean keyUp(Event evt, int nKey)
{
// Получаем контекст отображения
Graphics g = getGraphics();
// Выполняем свертку нижней области окна
g.copyArea(0, 1,
dimAppWndDimension.width - 1,
dimAppWndDimension.height - yHeight - 5,
0, yHeight + 1);
// Закрашиваем область ввода желтым цветом
g.setColor(Color.yellow);
g.fillRect(1, 1,
dimAppWndDimension.width - 2, yHeight + 1);
return true;
}
}
В листинге 4.6 вы найдете исходный текст документа HTML, в который встроен наш аплет.
Листинг 4.6. Файл KeyCode\KeyCode.html
<html>
<head>
<title>KeyCode</title>
</head>
<body>
<hr>
<applet
code=KeyCode.class
id=KeyCode
width=320
height=240 >
</applet>
<hr>
<a href="KeyCode.java">The source.</a>
</body>
</html>
Исходные тексты приложения TextOut
Файл исходного текста приложения TextOut представлен в листинге 3.5.
Листинг 3.5. Файл TextOut\TextOut.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 TextOut extends Applet
{
// -------------------------------------------------------
// Поля класса.
// Создаются автоматически для всех параметров аплета
// -------------------------------------------------------
private String m_Str1 = "Hello 1";
private String m_Str2 = "Hello 2";
private String m_Str3 = "Hello 3";
private String m_Str4 = "Hello 4";
private String m_Str5 = "Hello 5";
private String m_Font1 = "Arial";
private String m_Font2 = "Courier";
private String m_Font3 = "Times";
private String m_Font4 = "Helvetica";
private String m_Font5 = "Undefined";
private String m_Type1 = "Bold";
private String m_Type2 = "Italic";
private String m_Type3 = "Plain";
// -------------------------------------------------------
// Имена параметров
// -------------------------------------------------------
private final String PARAM_Str1 = "Str1";
private final String PARAM_Str2 = "Str2";
private final String PARAM_Str3 = "Str3";
private final String PARAM_Str4 = "Str4";
private final String PARAM_Str5 = "Str5";
private final String PARAM_Font1 = "Font1";
private final String PARAM_Font2 = "Font2";
private final String PARAM_Font3 = "Font3";
private final String PARAM_Font4 = "Font4";
private final String PARAM_Font5 = "Font5";
private final String PARAM_Type1 = "Type1";
private final String PARAM_Type2 = "Type2";
private final String PARAM_Type3 = "Type3";
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: TextOut\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_Str1, "String", "Text string to write" },
{ PARAM_Str2, "String", "Text string to write" },
{ PARAM_Str3, "String", "Text string to write" },
{ PARAM_Str4, "String", "Text string to write" },
{ PARAM_Str5, "String", "Text string to write" },
{ PARAM_Font1, "String", "Text font" },
{ PARAM_Font2, "String", "Text font" },
{ PARAM_Font3, "String", "Text font" },
{ PARAM_Font4, "String", "Text font" },
{ PARAM_Font5, "String", "Text font" },
{ PARAM_Type1, "String", "Font type" },
{ PARAM_Type2, "String", "Font type" },
{ PARAM_Type3, "String", "Font type" },
};
return info;
}
// -------------------------------------------------------
// init
// Вызывается во время инициализации аплета
// -------------------------------------------------------
public void init()
{
// Рабочая переменная для получения параметров
String param;
// Получение параметров и сохранение
// их значений в полях класса
// Строки, которые будут выведены в окно аплета
param = getParameter(PARAM_Str1);
if (param != null)
m_Str1 = param;
param = getParameter(PARAM_Str2);
if (param != null)
m_Str2 = param;
param = getParameter(PARAM_Str3);
if (param != null)
m_Str3 = param;
param = getParameter(PARAM_Str4);
if (param != null)
m_Str4 = param;
param = getParameter(PARAM_Str5);
if (param != null)
m_Str5 = param;
// Шрифты для отображения строк
param = getParameter(PARAM_Font1);
if (param != null)
m_Font1 = param;
param = getParameter(PARAM_Font2);
if (param != null)
m_Font2 = param;
param = getParameter(PARAM_Font3);
if (param != null)
m_Font3 = param;
param = getParameter(PARAM_Font4);
if (param != null)
m_Font4 = param;
param = getParameter(PARAM_Font5);
if (param != null)
m_Font5 = param;
// Начертание шрифтов
param = getParameter(PARAM_Type1);
if (param != null)
m_Type1 = param;
param = getParameter(PARAM_Type2);
if (param != null)
m_Type2 = param;
param = getParameter(PARAM_Type3);
if (param != null)
m_Type3 = param;
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
{
// Начальная координата для вывода по вертикали
int yStart = 20;
// Текущая координата для вывода строки
int yCurrent = 20;
// Определяем текущие размеры окна аплета
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);
// Получаем стиль шрифта и выбираем шрифт
// в соответствии с этим стилем
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));
// Отступ для первой строки
yCurrent += yStart;
// Рисуем первую строку
g.drawString(m_Str1, 10, yCurrent);
// Определяем метрики шрифта
FontMetrics fm = g.getFontMetrics();
// Устанавливаем новую текущую позицию для
// вывода очередной строки
yCurrent += fm.getHeight();
// Выбираем шрифт в контекст отображения
if(m_Type1.equals("Bold"))
g.setFont(new Font(m_Font2, Font.BOLD, 25));
else if(m_Type1.equals("Italic"))
g.setFont(new Font(m_Font2, Font.ITALIC, 25));
else if(m_Type1.equals("Plain"))
g.setFont(new Font(m_Font2, Font.PLAIN, 25));
// Рисуем вторую строку
g.drawString(m_Str2, 10, yCurrent);
// Устанавливаем новую текущую позицию для
// вывода очередной строки
fm = g.getFontMetrics();
yCurrent += fm.getHeight();
// Выбираем шрифт в контекст отображения
if(m_Type2.equals("Bold"))
g.setFont(new Font(m_Font3, Font.BOLD, 25));
else if(m_Type2.equals("Italic"))
g.setFont(new Font(m_Font3, Font.ITALIC, 25));
else if(m_Type2.equals("Plain"))
g.setFont(new Font(m_Font3, Font.PLAIN, 25));
// Рисуем третью строку
g.drawString(m_Str3, 10, yCurrent);
// Устанавливаем новую текущую позицию для
// вывода очередной строки
fm = g.getFontMetrics();
yCurrent += fm.getHeight();
// Выбираем шрифт в контекст отображения
if(m_Type2.equals("Bold"))
g.setFont(new Font(m_Font4, Font.BOLD, 25));
else if(m_Type2.equals("Italic"))
g.setFont(new Font(m_Font4, Font.ITALIC, 25));
else if(m_Type2.equals("Plain"))
g.setFont(new Font(m_Font4, Font.PLAIN, 25));
// Рисуем четвертую строку
g.drawString(m_Str4, 10, yCurrent);
// Устанавливаем новую текущую позицию для
// вывода очередной строки
fm = g.getFontMetrics();
yCurrent += fm.getHeight();
// Выбираем шрифт в контекст отображения
if(m_Type3.equals("Bold"))
g.setFont(new Font(m_Font5, Font.BOLD, 25));
else if(m_Type3.equals("Italic"))
g.setFont(new Font(m_Font5, Font.ITALIC, 25));
else if(m_Type3.equals("Plain"))
g.setFont(new Font(m_Font5, Font.PLAIN, 25));
// Рисуем пятую строку
g.drawString(m_Str5, 10, yCurrent);
}
}
Исходный текст документа HTML, в который встроен аплет TextOut, приведен в листинге 3.6.
Листинг 3.6. Файл TextOut\TextOut.html
<html>
<head>
<title>TextOut</title>
</head>
<body>
<hr>
<applet
code=TextOut.class
id=TextOut
width=320
height=240 >
<param name=Str1 value="Hello 1">
<param name=Str2 value="Hello 2">
<param name=Str3 value="Hello 3">
<param name=Str4 value="Hello 4">
<param name=Str5 value="Hello 5">
<param name=Font1 value="Dialog">
<param name=Font2 value="Courier">
<param name=Font3 value="TimesRoman">
<param name=Font4 value="Helvetica">
<param name=Font5 value="Undefined">
<param name=Type1 value="Bold">
<param name=Type2 value="Italic">
<param name=Type3 value="Plain">
</applet>
<hr>
<a href="TextOut.java">The source.</a>
</body>
</html>
Исходный текст приложения
Исходный текст приложения представлен в листинге 3.3.
Листинг 3.3. Файл FontList\FontList.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 FontList extends Applet
{
// -------------------------------------------------------
// Поля класса
// -------------------------------------------------------
Toolkit toolkit; // ссылка на Toolkit
String fntlist[]; // список шрифтов
int yStart = 20; // координата Y начала области вывода
int yStep; // шаг вывода строк с названиями шрифтов
// -------------------------------------------------------
// getAppletInfo
// Метод, возвращающей строку информации об аплете
// -------------------------------------------------------
public String getAppletInfo()
{
return "Name: FontList\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";
}
// -------------------------------------------------------
// init
// Вызывается во время инициализации аплета
// -------------------------------------------------------
public void init()
{
// Получаем ссылку на Toolkit
toolkit = Toolkit.getDefaultToolkit();
// Получаем список доступных шрифтов
fntlist = toolkit.getFontList();
}
// -------------------------------------------------------
// paint
// Метод paint, выполняющий рисование в окне аплета
// -------------------------------------------------------
public void paint(Graphics g)
{
// Определяем метрики шрифта
FontMetrics fm = g.getFontMetrics();
// Устанавливаем шаг вывода строк по вертикали
// равным полной высоте символов текущего шрифта
yStep = fm.getHeight();
// Устанавливаем новую высоту аплета исходя
// из количества элементов в списке шрифтов
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);
}
}
}
В листинге 3.4 вы найдете исходный текст документа HTML, в который встроен наш аплет.
Листинг 3.4. Файл FontList\FontList.html
<html>
<head>
<title>FontList</title>
</head>
<body>
<hr>
<applet
code=FontList.class
id=FontList
width=320
height=240 >
</applet>
<hr>
<a href="FontList.java">The source.</a>
</body>
</html>
Как обрабатываются события
Когда возникает событие, управление получает метод handleEvent из класса Component. Класс Applet является дочерним по отношению к классу Component.
Прототип метода handleEvent мы привели ниже:
public boolean handleEvent(Event evt);
В качестве параметра методу handleEvent передается объект класса Event, который содержит всю информацию о событии. По содержимому полей класса Event вы можете определить координаты курсора мыши в момент, когда пользователь нажал клавишу, отличить одинарный щелчок от двойного и так далее.
Ниже мы привели список полей класса Event, которые вы можете проанализировать:
Поле | Описание | ||
public Object arg; | Произвольный аргумент события, значение которого зависит от типа события | ||
public int clickCount; | Это поле имеет значение только для события с типом MOUSE_DOWN и содержит количество нажатий на клавишу мыши. Если пользователь сделал двойной щелчок мышью, в это поле будет записано значение 2 | ||
public Event evt; | Следующее событие в связанном списке | ||
public int id; | Тип события. Ниже мы перечислим возможные значения для этого поля | ||
public int key; | Код нажатой клавиши (только для события, созданного при выполнении пользователем операции с клавиатурой) | ||
public int modifiers; | Состояние клавиш модификации <Alt>, <Ctrl>, <Shift> | ||
public Object target; | Компонент, в котором произошло событие | ||
public long when; | Время, когда произошло событие | ||
public int x; | Координата по оси X | ||
public int y; | Координата по оси Y |
Поле id (тип события) может содержать следующие значения:
Значение | Тип события | ||
ACTION_EVENT | Пользователь хочет, чтобы произошло некоторое событие | ||
GOT_FOCUS | Компонент (в нашем случае окно аплета) получил фокус ввода. О фокусе ввода вы узнаете из раздела, посвященного работе с клавиатурой | ||
KEY_ACTION | Пользователь нажал клавишу типа “Action” | ||
KEY_ACTION_RELEASE | Пользователь отпустил клавишу типа “Action” | ||
KEY_PRESS | Пользователь нажал обычную клавишу | ||
KEY_RELEASE | Пользователь отпустил обычную клавишу | ||
LIST_DESELECT | Отмена выделения элемента в списке | ||
LIST_SELECT | Выделение элемента в списке | ||
LOAD_FILE | Загрузка файла | ||
LOST_FOCUS | Компонент потерял фокус ввода | ||
MOUSE_DOWN | Пользователь нажал клавишу мыши | ||
MOUSE_DRAG | Пользователь нажал клавишу мыши и начал выполнять перемещение курсора мыши | ||
MOUSE_ENTER | Курсор мыши вошел в область окна аплета | ||
MOUSE_EXIT | Курсор мыши покинул область окна аплета | ||
MOUSE_MOVE | Пользователь начал выполнять перемещение курсора мыши, не нажимая клавишу мыши | ||
MOUSE_UP | Пользователь отпустил клавишу мыши | ||
SAVE_FILE | Сохранение файла | ||
SCROLL_ABSOLUTE | Пользователь переместил движок полосы просмотра в новую позицию | ||
SCROLL_LINE_DOWN | Пользователь выполнил над полосой просмотра операцию сдвига на одну строку вниз | ||
SCROLL_LINE_UP | Пользователь выполнил над полосой просмотра операцию сдвига на одну строку вверх | ||
SCROLL_PAGE_DOWN | Пользователь выполнил над полосой просмотра операцию сдвига на одну страницу вниз | ||
SCROLL_PAGE_UP | Пользователь выполнил над полосой просмотра операцию сдвига на одну страницувверх | ||
WINDOW_DEICONIFY | Пользователь запросил операцию восстановления нормального размера окна после его минимизации | ||
WINDOW_DESTROY | Пользователь собирается удалить окно | ||
WINDOW_EXPOSE | Окно будет отображено | ||
WINDOW_ICONIFY | Окно будет минимизировано | ||
WINDOW_MOVED | Окно будет перемещено |
Если событие связано с клавиатурой (тип события KEY_ACTION или KEY_ACTION_RELEASE), в поле key может находиться одно из следующих значений:
Значение |
Клавиша |
DOWN |
Клавиша перемещения курсора вниз |
END |
<End> |
F1 |
<F1> |
F2 |
<F2> |
F3 |
<F3> |
F4 |
<F4> |
F5 |
<F5> |
F6 |
<F6> |
F7 |
<F7> |
F8 |
<F8> |
F9 |
<F9> |
F10 |
<F10> |
F11 |
<F11> |
F12 |
<F12> |
HOME |
<Home> |
LEFT |
Клавиша перемещения курсора влево |
PGDN |
<Page Down> |
PGUP |
<Page Up> |
RIGHT |
Клавиша перемещения курсора вправо |
UP |
Клавиша перемещения курсора вниз |
Значение маски |
Описание |
ALT_MASK |
Была нажата клавиша <Alt> |
META_MASK |
Была нажата мета-клавиша (клавиша для ввода диактрических символов) |
CTRL_MASK |
Была нажата клавиша <Ctrl> |
SHIFT_MASK |
Была нажата клавиша <Shift> |
Как связаться с авторами
Полную информацию о всех наших книгах серий “Библиотека системного программиста” и “Персональный компьютер. Шаг за шагом”, а также дискеты к книгам, статьи и другую информацию вы можете найти в сети Internet на серверах Web по следующим адресам:
http://www.glasnet.ru/~frolov
http://www.dials.ccas.ru/frolov
Вы можете передать нам свои замечания и предложения по содержанию этой и других наших книг через электронную почту по адресам:
frolov@glas.apc.org
frolov.alexandr@usa.net
Если электронная почта вам недоступна, присылайте ваши отзывы в АО “Диалог-МИФИ” по адресу:
115409, Москва, ул. Москворечье, 31, корп. 2,
тел. 324-43-77
Приносим свои извинения за то что не можем ответить на каждое письмо. Мы также не занимаемся продажей и рассылкой книг, дискет, рекламы, отдельных фрагментов наших книг и исходных текстов к книгам, консультациями через электронную почту. По вопросам приобретения книг и дискет обращайтесь непосредственно в издательство “Диалог-МИФИ”.
Класс FirstPanel
Класс FirstPanel создан на базе класса Panel:
class FirstPanel extends Panel
{
public void paint(Graphics g)
{
. . .
super.paint(g);
}
}
В нашем приложении мы создаем верхнюю панель как объект этого класса. Единственный метод, переопределенный в классе FirstPanel - это метод paint.
Класс MainFrameWnd
Класс MainFrameWnd предназначен для создания автономного перекрывающегося окна, которое существует вне окна навигатора. Этот класс был нами создан на базе класса Frame:
class MainFrameWnd extends Frame
{
. . .
}
В классе мы определили несколько полей, конструктор для создания окна, метод paint для рисования в окне, метод handleEvent для обработки запроса на уничтожение окна, метод action для обработки события, вызванного кнопкой, расположенной в окне, а также выбором строк меню, созданного для окна.
Класс MessageBox
Для отображения названий выбранных строк меню мы создаем диалоговую панель, определив свой класс MessageBox на базе класса Dialog, как это показано ниже:
class MessageBox extends Dialog
{
. . .
}
В классе MessageBox есть два поля, конструктор, методы handleEvent и action.
Класс SecondPanel
Класс SecondPanel создан также на базе класса Panel:
class SecondPanel extends Panel
{
public void paint(Graphics g)
{
. . .
super.paint(g);
}
}
С использованием этого класса создается нижняя панель. В классе SecondPanel, как и в классе FirstPanel, переопределен метод paint.
Класс String
Класс String предназначен для работы с такими часто встречающимися объектами, как текстовые строки. Методы этого класса позволяют выполнять над строками практически все операции, которые вы делали раньше при помощи библиотечных функций C. Это преобразование строки в число и обратно с любым заданным основанием, определение длины строки, сравнение строк, извлечение подстроки и так далее.
Хотя в языке Java не допускается перезагрузка (переопределение) операторов, для объектов класса Stirng и объектов всех произошедших от него классов сделана встроенная перезагрузка операторов “+” и “+=”. С помощью этих операторов можно выполнять слияние текстовых строк, например:
System.out.println(“x = “ + x + ‘\n’);
Здесь в качестве параметра функции println передается текстовая строка, составленная из трех компонент: строки “x = “, числа x и символа перехода на следующую строку ‘\n’. Значение переменной x автоматически преобразуется в текстовую строку (что выполняется только для текстовых строк) и полученная таким образом текстовая строка сливается со строкой “x = “.
Классы Menu и MenuItem
Для того чтобы дать вам представление о том, что можно делать с меню, приведем краткое описание класса Menu:
public class java.awt.Menu
extends java.awt.MenuItem
implements java.awt.MenuContainer
{
// -----------------------------------------------------
// Конструкторы
// -----------------------------------------------------
// Создание меню с заданным названием
public Menu(String label);
// Создание меню с заданным названием,
// которое может оставаться на экране после того как
// пользователь отпустил клавишу мыши
public Menu(String label, boolean tearOff);
// -----------------------------------------------------
// Методы
// -----------------------------------------------------
// Добавление элемента меню
public MenuItem add(MenuItem mi);
// Добавление строки в меню
public void add(String label);
// Вызов метода createMenu
public void addNotify();
// Добавление разделителя в меню
public void addSeparator();
// Определение количества строк в меню
public int countItems();
// Получение ссылки на элемент меню с заданным номером
public MenuItem getItem(int index);
// Проверка, остается ли меню на экране после того как
// пользователь отпустил клавишу мыши
public boolean isTearOff();
// Удаление заданного элемента меню
public void remove(int index);
// Удаление заданной компоненты меню
public void remove(MenuComponent item);
// Извещение об удалении меню
public void removeNotify();
}
Метод addSeparator используется для добавления в меню разделительной строки. Аналогичный результат достигается и при добавлении в меню стоки “-“:
mnHelp.add("-");
Заметим, что вы можете просто добавлять в меню строки по их названию, пользуясь методом add(String label), либо добавлять в меню элементы класса MenuItem, вызывая метод add(MenuItem mi).
Класс MenuItem определяет поведение отдельных элементов меню:
public class java.awt.MenuItem
extends java.awt.MenuComponent
{
// -----------------------------------------------------
// Конструктор
// -----------------------------------------------------
public MenuItem(String label);
// -----------------------------------------------------
// Методы
// -----------------------------------------------------
// Вызов метода createMenuItem
public void addNotify();
// Блокирование элемента меню
public void disable();
// Разблокирование элемента меню
public void enable();
// Блокирование или разблокирование элемента меню
public void enable(boolean cond);
// Получение текстовой строки меню
public String getLabel();
// Проверка, является ли элемент меню заблокированным
public boolean isEnabled();
// Получение строки параметров
public String paramString();
// Установка текстовой строки для элемента меню
public void setLabel(String label);
}
Пользуясь методами класса MenuItem вы можете блокировать или разблокировать отдельные строки меню, что нужно делать, например, если в данный момент функция, соответствующая строке меню, недоступна или не определена. Вы также можете изменять текстовые строки, соответствующие элементам меню, что может пригодиться для переопределения их назначения.
Кнопки
Как мы уже говорили, стандартные кнопки создаются на базе класса Button. Этот класс очень простой, поэтому мы приведем его определение полностью:
public class java.awt.Button
extends java.awt.Component
{
// -----------------------------------------------------
// Конструкторы
// -----------------------------------------------------
public Button();
public Button(String label);
// -----------------------------------------------------
// Методы
// -----------------------------------------------------
// Вызов метода createButton
public void addNotify();
// Получение надписи на кнопке
public String getLabel();
// Получение строки параметров, отражающей
// состоние кнопки
protected String paramString();
// Установка надписи на кнопке
public void setLabel(String label);
}
В классе Button определены два конструктора, первый из которых позволяет создавать кнопку без надписи, а второй - кнопку с надписью. Обычно используется именно второй конструктор.
Из методов класса Button вы будете использовать чаще всего два - getLabel и setLabel. Первый из них позволяет получить строку надписи на кнопке, а второй - установить новую надпись.
Обычно аплет создает в своем окне кнопки в процессе своей инициализации при обработке метода init, например:
Button btn1;
. . .
public void init()
{
btn1 = new Button("Button 1");
add(btn1);
}
Здесь мы создали кнопку с надписью Button 1 и добавили ее в контейнер, которым является окно аплета, с помощью метода add.
Конструктор HelloAp
Конструктор клсса HelloAp находится в одноименном методе и вызывается при создании объекта класса:
public HelloAp()
{
// Сделать: Добавьте сюда код конструктора
}
По умолчанию тело конструктора, создаваемого системой Java Applet Wizard, не содержит никакого кода. Однако вы можете добавить сюда строки, выполняющие инициализацию аплета при его создании как объекта.
Конструктор класса MainFrameWnd
В качестве единственного параметра нашему конструктору передается заголовок создаваемого окна. В первой исполняемой строке наш конструктор вызывает конструктор из базового класса, передавая ему строку заголовка через параметр:
super(sTitle);
Далее конструктор определяет размеры окна, вызывая для него метод resize:
resize(400, 200);
Затем мы устанавливаем для нашего окна желтый цвет фона и черный цвет изображения:
setBackground(Color.yellow);
setForeground(Color.black);
По умолчанию для окон класса Frame устанавливается режим добавления компонент BorderLayout. Мы изменяем этот режим на FlowLayout, вызывая метод setLayout:
setLayout(new FlowLayout());
Установив новый режим добавления компонент, мы располагаем в нашем окне кнопку, предварительно создав ее с помощью конструктора класса Button:
btnOK = new Button("OK");
add(btnOK);
Далее метод init приступает к формированию главного меню окна. Это меню создается как объект класса MenuBar:
mbMainMenuBar = new MenuBar();
Затем мы создаем и наполняем меню “File”:
mnFile = new Menu("File");
mnFile.add("New"); // строка New
mnFile.add("-"); // разделитель
mnFile.add("Exit"); // строка Exit
Это меню создается на базе класса Menu. Обратите внимание, что между строками New и File расположен разделитель.
Аналогичным образом мы добавляем в главное меню другое меню - “Help”:
mnHelp = new Menu("Help");
mnHelp.add("Content"); // строка Content
mnHelp.add("-"); // разделитель
mnHelp.add("About"); // строка About
После своего окончательного формирования меню “File” и “Help” добавляются в главное меню окна mbMainMenuBar:
mbMainMenuBar.add(mnFile);
mbMainMenuBar.add(mnHelp);
И, наконец, когда главное меню будет сформировано, оно подключается к окну вызовом метода setMenuBar, как это показано ниже:
setMenuBar(mbMainMenuBar);
Конструктор класса MessageBox
Наш конструктор создает диалоговую панель с заданным сообщением внутри нее. Ссылка на строку сообщения передается конструктору через первый параметр. Остальные параметры используются конструктором базового класса Dialog для создания диалоговой панели:
super(parent, sTitle, modal);
После вызова конструктора из базового класса наш конструктор устанавливает размеры окна созданной диалоговой панели, вызывая метод resize:
resize(200, 100);
Отменяя установленный по умолчанию режим размещения компонент BorderLayout, конструктор устанавливает режим GridLayout:
setLayout(new GridLayout(2, 1));
Окно диалоговой панели при этом разделяется на две части по горизонтали. В верхнюю часть добавляется текстовое поле для отображения сообщения, в нижнюю - кнопка OK:
lbMsg = new Label(sMsg, Label.CENTER);
add(lbMsg);
btnOK = new Button("OK");
add(btnOK);
Контекст отображения
Способ, которым аплет выполняет рисование в своем окне, полностью отличается от того, которым пользуются программы MS-DOS. Вместо того чтобы обращаться напрямую или через драйвер к регистрам видеоконтроллера, аплет пользуется методами из класса Graphics. Эти методы инкапсулируют все особенности аппаратуры, предоставляя в распоряжение программиста платформно-независимое средство рисования.
Для окна аплета создается объект класса Graphics, ссылка на который передается методу paint. В предыдущей главе мы уже пользовались этим объектом, вызывая для него метод drawString, рисующий в окне текстовую строку. Объект, ссылка на который передается методу paint, и есть контекст отображения. Сейчас мы займемся контекстом отображения вплотную.
Копирование содержимого прямоугольной области
Метод copyArea позволяет скопировать содержимое любой прямоугольной области окна аплета:
public abstract void
copyArea(int x, int y, int width,
int height, int dx, int dy);
Параметры x, y, width и height задают координаты копируемой прямоугольной области. Область копируется в другую прямоугольную область такого же размера, причем параметры dx и dy определяют координаты последней.
Линии
Для того чтобы нарисовать прямую тонкую сплошную линию, вы можете воспользоваться методом drawLine, прототип которого приведен ниже:
public abstract void drawLine(int x1, int y1,
int x2, int y2);
Концы линии имеют координаты (x1, y1) и (x2, y2), как это показано нарис. 3.1.
Рис. 3.1. Рисование прямой линии
К сожалению, в контексте отображения не предусмотерны никакие атрибуты, позволяющие назрисовать пунктирную линию или линию увеличенной толщины.
Литература
1. Фролов А.В., Фролов Г.В. Библиотека системного программиста. М.: ДИАЛОГ-МИФИ
Т.11 - 13. Операционная система Microsoft Windows 3.1 для программиста, 1994
Т.14. Графический интерфейс GDI в Microsoft Windows, 1994
Т.15. Мультимедиа для Windows, 1994
Т.22. Операционная система Windows 95 для программиста, 1996
Т.23. Глобальные сети компьютеров. Практическое введение в Internet, E-Mail, FTP, WWW и HTML, программирование для Windows Sockets
Т.29. Сервер Web своими руками. Язык HTML, приложения CGI и ISAPI, установка серверов Web для Windows, 1997
2. Д. Родли, Создание Java-апплетов: Пер. с англ., К: НИПФ “ДиаСофт Лтд.”, 1996
3. S. Davic, Learn Lava Now, Microsoft Press, One Microsoft Way, 1996
4. К. Джамса, Java: Пер. с англ., Мн.: ООО “Поппури”, 1996
5. Баженова И.Ю.,Язык программирования Java, М.: ДИАЛОГ-МИФИ, 1997
Массивы в Java
Для создания массива вы можете пользоваться квадратными скобками, расположив их справа от имени массива или от типа объектов, из которых составлен массив, например:
int nNumbers[];
int[] nAnotherNumbers;
Допустимы оба варианта, поэтому вы можете выбрать тот, который вам больше нравится.
При определении массивов в языке Java нельзя указывать их размер. Приведенные выше две строки не вызывают резервирования памяти для массива. Здесь просто создаются ссылки на массивы, которые без инициализации использовать нельзя.
Для того чтобы заказать память для массива, вы должны создать соответствующие объекты с помощью ключевого слова new, например:
int[] nAnotherNumbers;
nAnotherNumbers = new int[15];
Как выполнить инициализацию ячеек таблицы?
Такую инициализацию можно выполнить либо статически, либо динамически. В первом случае вы просто перечисляете значения в фигурных скобках, как это показано ниже:
int[] nColorRed = {255, 255, 100, 0, 10};
Динамическая инициализация выполняется с использованием индекса массива, например, в цикле:
int nInitialValue = 7;
int[] nAnotherNumbers;
nAnotherNumbers = new int[15];
for(int i = 0; i < 15; i++)
{
nAnotherNumbers[i] = nInitialValue;
}
Вы можете создавать массивы не только из переменных базовых типов, но и из произвольных объектов. Каждый элемент такого массива должен инициализироваться оператором new.
Массивы могут быть многомерными и, что интересно, несимметричными.
Ниже создается массив массивов. В нулевом и первом элементе создается массив из четырех чисел, а во втором - из восьми:
int[][] nDim = new int[5][10];
nDim[0] = new int [4];
nDim[1] = new int [4];
nDim[2] = new int [8];
Заметим, что во время выполнения приложения Java виртуальная машина Java проверяет выход за границы массива. Если приложение пытается выйти за границы массива, происходит исключение.
Массивы в языке Java являются объектами некоторого встроенного класса. Для этого класса существует возможность определить размер массива, обратившись к элементу данных класса с именем length, например:
int[] nAnotherNumbers;
nAnotherNumbers = new int[15];
for(int i = 0; i < nAnotherNumbers.length; i++)
{
nAnotherNumbers[i] = nInitialValue;
}
Для определения размера массива вам не нужен такой оператор как sizeof из языка программирования С, так как существует другой способ определения размера массива.
Меню в окне класса Frame
Как мы уже говорили, окно класса Frame может иметь главное меню (Menu Bar) или, как еще говорят, строку меню. Главное меню создается на базе класса MenuBar, краткое описание которого приведено ниже:
public class java.awt.MenuBar
extends java.awt.MenuComponent
implements java.awt.MenuContainer
{
// -----------------------------------------------------
// Конструктор
// -----------------------------------------------------
public MenuBar();
// -----------------------------------------------------
// Методы
// -----------------------------------------------------
// Добавление меню в главное меню окна
public Menu add(Menu m);
// Вызов метода createMenuBar
public void addNotify();
// Определение количества меню, добавленных
// в главное меню
public int countMenus();
// Получение ссылки на меню Help
public Menu getHelpMenu();
// Получение ссылки на меню с заданным номером
public Menu getMenu(int i);
// Удаление меню с заданным номером из главного меню
public void remove(int index);
// Удаление компоненты меню
public void remove(MenuComponent m);
// Извещение об удалении меню
public void removeNotify();
// Установка меню Help
public void setHelpMenu(Menu m);
}
Для формирования главного меню окна вы должны создать объект класса MenuBar с помощью конструктора, а затем добавить в него отдельные меню.
Объект главного меню создается следующим образом:
MenuBar mbMainMenuBar;
mbMainMenuBar = new MenuBar();
Отдельные меню создаются на базе класса Menu, например:
Menu mnFile;
Menu mnHelp;
mnFile = new Menu("File");
mnHelp = new Menu("Help");
Создав меню, вы должны добавить в них строки. Для этого нужно вызвать метод add, передав ему в качестве параметра текст строки меню, например:
mnFile.add("New");
mnFile.add("-");
mnFile.add("Exit");
mnHelp.add("Content");
mnHelp.add("-");
mnHelp.add("About");
Далее сформированные меню добавляются в главное меню:
mbMainMenuBar.add(mnFile);
mbMainMenuBar.add(mnHelp);
И, наконец, теперь можно устанавливать главное меню в окне класса, созданного на базе класса Frame:
setMenuBar(mbMainMenuBar);
Метод action
Метод action проверяет, является ли объект, создавший событие, кнопкой. Для этого он сравнивает ссылку на объект, передаваемую через поле evt.target, с объектом Button, пользуясь оператором instanceof. Так как поле evt.target может содержать ссылку на любой объект, способный создавать события, а не только на объект типа Button, эта проверка необходима для исключения ложных срабатываний на чужие события.
Если событие создано кнопкой, ссылка на эту кнопку сохраняется в переменной btn:
Button btn;
btn = (Button)evt.target;
При этом мы выполняем преобразование типов.
Далее метод action получает название кнопки (то есть строку, написанную на поверхности кнопки) и сохраняет его в переменной sTextLabel:
sTextLabel = btn.getLabel();
Для получения строки названия кнопки используется метод getLabel, определенный в классе Button.
Затем метод action проверяет, от какой конкретно кнопки пришло событие, выполняя ветвление с помощью оператора if - else if - else:
if(evt.target.equals(btn1))
{
showStatus("Button 1 (\"" + sTextLabel + "\") pressed");
}
else if(evt.target.equals(btn2))
{
showStatus("Button 2 (\"" + sTextLabel + "\") pressed");
}
. . .
else
{
return false;
}
Название нажатой кнопки отображается в строке состояния навигатора. Если событие создано кнопкой, обработчик которой не предусмотрен в нашем методе action, метод просто возвращает значение false, отказываясь таким образом от обработки события.
Если ваша реализация метода action не обрабатывает событие, она может передать его методу action базового класса, как это показано ниже:
super.action(evt, obj);
В том случае, когда событие было обработано, метод action перерисовывает окно аплета, вызывая метод repaint, и затем возвращает значение true:
repaint();
return true;
Метод action обрабатывает только те события, которые вызваны кнопкой btnGet:
if(evt.target instanceof Button)
{
if(evt.target.equals(btnGet))
showStatus("Button 1 pressed");
else
return false;
repaint();
return true;
}
Когда пользователь нажимает кнопку, метод action выводит сообщение об этом в строку состояния навигатора и перерисывавает окно аплета. Текущее состояние кнопок определяется методом paint во время перерисовки окна.
Метод action обрабатывает событие, вызванное списками, - выбор элемента из списка.
Прежде всего, метод action сохраняет ссылку на список, в котором произошел выбор, в переменной ch:
Choice ch;
ch = (Choice)evt.target;
Далее выполняется проверка факта, что событие вызванно именно списком, после чего происходит анализ, в каком именно списке сделан выбор нового элемента:
if(evt.target.equals(chBackgroundColor))
{
if(ch.getSelectedIndex() == 0)
setBackground(Color.yellow);
else if(ch.getSelectedIndex() == 1)
setBackground(Color.green);
else if(ch.getSelectedIndex() == 2)
setBackground(Color.white);
}
else if(evt.target.equals(chForegroundColor))
{
if(ch.getSelectedIndex() == 0)
setForeground(Color.black);
else if(ch.getSelectedIndex() == 1)
setForeground(Color.red);
else if(ch.getSelectedIndex() == 2)
setForeground(Color.blue);
}
else
return false;
Обратите внимание, что мы вначале выполняем преобразование типа evt.target к классу Choice, а только затем проверяем, действительно ли событие вызвано списком. Правильно ли это?
Вообще говоря, неправильно. Так как в поле evt.target могут находиться ссылки на объекты различных классов, в процессе выполнения преобразования типов может произойти исключение. Если предпринимается попытка выполнить преобразование для несовместимых типов. Но так как в нашем аплете события создаются только списками, исключение не возникает.
Корректнее было бы вначале проверить ссылку evt.target на принаддлежность к классу Choice с помощью оператора instanceof, а только потом выполнять преобразование типов. Так мы и будем делать в следующих примерах аплетов, обрабатывающих события от различных источников.
С помощью метода getSelectedIndex метод action определяет номер выбранного элемента списка, устанавливая соответствующим образом цвет фона или изображения.
Метод action обрабатывает событие, вызванное списками, - выбор элемента из списка.
Прежде всего, метод action сохраняет ссылку на список, в котором произошел выбор, в переменной ch:
List ch;
ch = (List)evt.target;
Далее выполняется проверка факта, что событие вызванно именно списоком класса List, а затем обрабатываются события, созданные списками:
if(evt.target.equals(chBackgroundColor))
{
if(ch.getSelectedIndex() == 0)
setBackground(Color.yellow);
else if(ch.getSelectedIndex() == 1)
setBackground(Color.green);
else if(ch.getSelectedIndex() == 2)
setBackground(Color.white);
else if(ch.getSelectedIndex() == 3)
setBackground(Color.black);
else if(ch.getSelectedIndex() == 4)
setBackground(Color.red);
else if(ch.getSelectedIndex() == 5)
setBackground(Color.blue);
}
else if(evt.target.equals(chForegroundColor))
{
if(ch.getSelectedIndex() == 0)
setForeground(Color.black);
else if(ch.getSelectedIndex() == 1)
setForeground(Color.red);
else if(ch.getSelectedIndex() == 2)
setForeground(Color.blue);
else if(ch.getSelectedIndex() == 3)
setForeground(Color.yellow);
else if(ch.getSelectedIndex() == 4)
setForeground(Color.green);
else if(ch.getSelectedIndex() == 5)
setForeground(Color.white);
}
else
return false;
С помощью метода getSelectedIndex метод action определяет номер выбранного элемента списка, устанавливая соответствующим образом цвет фона или изображения. Затем метод перерисовывает окно аплета, вызывая метод repaint.
Наш метод action обрабатывает только те события, которые вызваны кнопками. Проверка источника события выполняется так же, как и раньше, поэтому мы не будем на этом останавливаться.
Что же касается установки выравнивания, то она выполняется при помощи метода setAlignment:
if(evt.target.equals(btnLeft))
lbTextLabel.setAlignment(Label.LEFT);
else if(evt.target.equals(btnCenter))
lbTextLabel.setAlignment(Label.CENTER);
else if(evt.target.equals(btnRight))
lbTextLabel.setAlignment(Label.RIGHT);
else
return false;
Наш метод action обрабатывает только те события, которые вызваны кнопкой.
Обработка заключается в извлечении текста из поля редактирования и записи его в строку str:
str = txt.getText();
repaint();
Наш метод action обрабатывает только те события, которые вызваны кнопками.
Обработка заключается в извлечении текста из поля редактирования и записи его в строку str. В зависимости от того, какая кнопка была нажата, извлекается либо весь текст, либо только выделенный фрагмент:
if(evt.target.equals(btnGetText))
{
str = txt.getText();
repaint();
}
else if(evt.target.equals(btnGetSelectedText))
{
str = txt.getSelectedText();
repaint();
}
else
return false;
Для извлечения всего текста мы вызываем метод getText, а для извлечения выделенного фрагмента - метод getSelectedText.
После записи извлеченного текста метод action перерисовывает окно аплета, вызывая метод repaint.
Метод action обрабатывает события, связанные с кнопками, расположенными в обеих панелях.
Вначале метод проверяет, что событие создано кнопкой. Далее идентификатор кнопки, вызвавшей событие, записывается в переменную btn:
btn = (Button)evt.target;
После этого метод action получает название кнопки, сохраняет его в строке sTextLabel, а затем отображает в строке состояния навигатора:
sTextLabel = btn.getLabel();
showStatus("Button (\"" + sTextLabel + "\") pressed");
Далее анализируется ссылка на кнопку. Если была нажата одна из управляющих кнопок, происходит перелистывание страниц блокнота, в прямом или обратном направлении:
if(evt.target.equals(btnNext))
{
((CardLayout)pCardPanel.getLayout()).next(pCardPanel);
}
else if(evt.target.equals(btnPrev))
{
((CardLayout)pCardPanel.getLayout()).previous(pCardPanel);
}
Здесь мы с помощью метода getLayout получаем ссылку на интерфейс системы Layout Manager, установленной для панели pCardPanel, а затем, пользуясь полученной ссылкой, вызываем методы next или previous. Обратите также внимание на необходимость явного приведения типа к классу CardLayout, в котором определены указанные методы.
Обработка событий, создаваемых кнопками, которые расположены на страницах блокнота, не имеет никаких особенностей:
else if(evt.target.equals(btn1))
{
showStatus("Button 1 (\"" + sTextLabel
+ "\") pressed");
}
. . .
else if(evt.target.equals(btn4))
{
showStatus("Button 4 (\"" + sTextLabel
+ "\") pressed");
}
Название кнопки просто отображается в строке состояния навигатора.
Метод action выполняет раздельную обработку событий, вызванных кнопками и списками.
Если событие было вызвано кнопками, выполняется переключение страниц блокнота:
if(evt.target.equals(btnNext))
((CardLayout)pCardPanel.getLayout()).next(pCardPanel);
else if(evt.target.equals(btnPrev))
((CardLayout)pCardPanel.getLayout()).previous(pCardPanel);
else if(evt.target.equals(btnBackgroundColor))
((CardLayout)pCardPanel.getLayout()).show(
pCardPanel, "BackgroundColor");
else if(evt.target.equals(btnForegroundColor))
((CardLayout)pCardPanel.getLayout()).show(
pCardPanel, "ForegroundColor");
else if(evt.target.equals(btnFont))
((CardLayout)pCardPanel.getLayout()).show(
pCardPanel, "Font");
Для выбора следующей и предыдущей страницы здесь использованы методы next и previous.
Выбор конкретной страницы по ее имени осуществляется с помощью метода show. В качестве параметров этому методу передается ссылка на панель блокнота и имя страницы.
Обратите также внимание на способ обработки событий, не имеющих отношения к нашим компонентам:
return super.action(evt, obj);
Здесь мы вызываем метод action из базового класса, который после соответствующей обработки события вернет значение true или false.
Если событие вызвано кнопками управления блокнотом, мы перерисовываем окно верхней панели, окно всего аплета и затем возвращаем признак успешной обработки события:
pDraw.repaint();
repaint();
return true;
Как вы увидите дальше, в процессе перерисовки окна всего аплета метод paint выполнит рисование в окне верхней панели.
События, связанные с выбором нового цвета фона и изображения обрабатываются следующим образом:
if(evt.target.equals(chBackgroundColor))
{
if(ch.getSelectedIndex() == 0)
pDraw.setBackground(Color.yellow);
else if(ch.getSelectedIndex() == 1)
pDraw.setBackground(Color.green);
else if(ch.getSelectedIndex() == 2)
pDraw.setBackground(Color.white);
}
else if(evt.target.equals(chForegroundColor))
Метод action класса FrameWnd
Назначение метода action класса FrameWnd - обработка событий, вызванных кнопками кнопку “Show Frame Window” и “Hide Frame Window”, созданных в окне аплета:
if(evt.target.equals(btnShowFrame))
fMainFrame.show();
else if(evt.target.equals(btnHideFrame))
fMainFrame.hide();
Если нажата кнопка “Show Frame Window”, для окна fMainFrame вызывается метод show, что приводит к появлению окна на экране. Если нажата кнопка “Hide Frame Window”, для этого окна вызывается метод hide, после чего окно исчезает с экрана. Исчезнувшее окно не уничтожается и вы можете снова отобразить его на экране, нажав кнопку “Show Frame Window”.
Метод action класса MainFrameWnd
Этот метод обрабатывает события, связанные с кнопкой и меню.
Если пользователь нажимает на кнопку OK, расположенную в окне, окно скрывается методом hide:
if(evt.target.equals(btnOK))
{
hide();
}
Здесь для вас нет ничего нового.
Рассмотрим более подробно процедуру обработки событий от меню.
Вначале метод action проверяет, вызвано ли событие выбором строки из меню, сравнивая объект события с классом MenuItem:
else if(evt.target instanceof MenuItem)
{
. . .
}
else
return false;
Если это так, в поле mnItem сохраняется ссылка на элемент меню, вызвавший событие:
mnItem = (MenuItem)evt.target;
Однако мы не используем этот элемент, так как для определения строки, выбранной пользователем, нам достаточно проанализировать второй параметр метода action:
if(obj.equals("Exit"))
System.exit(0);
else if(obj.equals("New"))
{
MessageBox mbox;
mbox = new MessageBox("Item New selected",
this, "Dialog from Frame", true);
mbox.show();
}
else if(obj.equals("Content"))
{
. . .
}
else if(obj.equals("About"))
{
. . .
}
В данном случае второй параметр метода action будет представлять собой ссылку на строку, выбранную из меню, поэтому для определения выбранной строки мы можем выполнить простое сравнение методом equals.
Если пользователь выбрал из меню File строку Exit, мы вызываем метод System.exit, предназначенный для завершения работы виртуальной машины Java. Таким способом вы можете завершить работу аплета, когда он выполняется в среде Microsoft Visual J++ в процессе отладки. Если же аплет запущен автономно в навигаторе, то завершения работы навигатора не произойдет.
В том случае когда пользователь выбирает любую другую строку из меню, метод action создает диалоговую панель на базе определенного нами класса MessageBox. В этой диалоговой панели отображаетя название выбранной строки меню.
Заметим, что сразу после создания конструктором диалоговая панель не появляется на экране. Мы отображаем ее, вызывая метод show.
Метод action класса MessageBox
Если пользователь нажимает кнопку OK, расположенную в окне диалоговой панели, метод action вызывает для панели метод dispose, удаляя эту панель с экрана и из памяти:
if(evt.target.equals(btnOK))
{
dispose();
}
Метод destroy
Перед удалением аплета из памяти вызывается метод destroy, который определен в базовом классе Applet как пустая заглушка. Система Java Applet Wizard добавляет в исходный текст класса переопределение метода destroy, которое выглядит следующим образом:
public void destroy()
{
// Сделать: Добавьте сюда код завершения работы аплета
}
Здесь вы можете выполнить все необходимые операции, которые следует выполнить перед удалением аплета. Например, если в методе init вы создавали какие-либо задачи, в методе destroy вы можете их завершить.
Метод destroy класса FrameWnd
При завершении работы аплета мы удаляем созданное нами окно и освобождаем все связанные с ним ресурсы, вызывая для окна метод dispose:
fMainFrame.dispose();
Метод getAppletInfo
Базовый класс Applet содержит определение метода getAppletInfo, возвращающее значение null. В нашем классе HelloAp, который является дочерним по отношению к классу Applet, система Java Applet Wizard переопределила метод getAppletInfo из базового класса следующим образом:
public String getAppletInfo()
{
return "Name: HelloAp\r\n" +
"Author: Alexandr Frolov\r\n" +
"Created with Microsoft Visual J++ Version 1.0";
}
Теперь этот метод возвращает текстовую информацию об аплете в виде объекта класса String.
Заметьте, что здесь возвращается достаточно длинная строка. Она разделена на три части, но способ разделения отличен от принятого в языке программирования С: части строки объединены оператором “+”. Для объектов класса String этот оператор в языке Java переопределен и имеет очевидное назначение - слияние строк.
В методе getAppletInfo изменения невелики: в описание аплета был добавлен наш почтовый адрес E-mail и адрес нашего сервера WWW:
public String getAppletInfo()
{
return "Name: Painter\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";
}
Метод getAppletInfo ничем не отличается от аналогичных методов в предыдущих приложениях.
Метод getAppletInfo возвращает информацию об аплете и не имеет никаких особенностей.
Метод getAppletInfo возвращает информацию об аплете и не имеет никаких особенностей.
Метод getAppletInfo, возвращающий строку информации об аплете, не имеет никаких особенностей.
Метод getAppletInfo возвращает информацию о нашем аплете.
Метод getAppletInfo возвращает информацию об аплете ChoiceList.
Метод getAppletInfo возвращает информацию об аплете ListBox.
Метод getAppletInfo возвращает информацию о нашем аплете.
Метод getAppletInfo возвращает информацию о нашем аплете.
Метод getAppletInfo возвращает информацию о нашем аплете.
Метод getAppletInfo возвращает информацию об аплете и не имеет никаких особенностей.
Метод getAppletInfo возвращает информацию об аплете.
Метод getAppletInfo класса FrameWnd
Этот метод возвращает информацию об аплете FrameWnd.
Метод getAppletInfo возвращает информацию об
Метод getAppletInfo возвращает информацию об аплете.
Метод getParameterInfo
Система Java Applet Wizard переопределяет метод getParameterInfo, который возвращает ссылку на массив массивов с описаниями параметров:
public String[][] getParameterInfo()
{
String[][] info =
{
{ PARAM_Str1, "String", "Text string to write" },
. . .
{ PARAM_Str5, "String", "Text string to write" },
{ PARAM_Font1, "String", "Text font" },
. . .
{ PARAM_Font5, "String", "Text font" },
{ PARAM_Type1, "String", "Font type" },
{ PARAM_Type2, "String", "Font type" },
{ PARAM_Type3, "String", "Font type" },
};
return info;
}
Как мы уже говорили, эта информация может использоваться другими аплетами, размещенными в том же документе HTML и работающими одновременно с нашим аплетом.
Метод handleEvent
Для того чтобы отследить выделение элементов списка, наш аплет переопределил метод handleEvent, обеспечив обработку события с идентификатором Event.LIST_SELECT.
Переопределение метода handleEvent нужно делать внимательно, так как этот метод вызывается при возникновении разных событий, например, при перемещении мыши в окне аплета. Если ваш метод handleEvent не обрабатывает какое-либо событие, он должен передать его одноименному методу из базового класса.
Наш метод handleEvent прежде всего проверяет код события, обрабатывая только события Event.LIST_SELECT, которые создаются при выделении пользователем элементов списка:
if(evt.id == Event.LIST_SELECT)
{
. . .
}
else
return super.handleEvent(evt);
Если событие подлежит обработке, наш метод handleEvent получает ссылку на объект, вызвавший событие, и сохраняет ее в переменной ls типа List:
List ls;
ls = (List)evt.target;
Затем метод определяет, какой сисок создал событие, проверяя поле evt.target, а затем получает и записывает выделенную строку в переменную sSelBackground (для списка цветов фона) или sSelForeground (для списка цветов изображения):
if(evt.target.equals(chBackgroundColor))
sSelBackground = ls.getSelectedItem();
else if(evt.target.equals(chForegroundColor))
sSelForeground = ls.getSelectedItem();
После этого цвет фона и изображения записывается в строку состояния навигатора в формате (<цвет фона>, <цвет изображения>):
showStatus("(" + sSelBackground + ",
" + sSelForeground + ")");
После этого метод выполняет перерисовку окна и возвращает значение true - признак того, что он обработал событие:
repaint();
return true;
Метод handleEvent класса MainFrameWnd
Для того чтобы определить реакцию окна на попытку пользователя закрыть окно с помощью органов управления, расположенных в заголовке окна, или другим способом, мы переопределили метод handleEvent.
При получении кода события Event.WINDOW_DESTROY (удаление окна) мы просто скрываем окно, вызывая метод hide:
if(evt.id == Event.WINDOW_DESTROY)
{
hide();
return true;
}
else
return super.handleEvent(evt);
Все другие события передаются для обработки методу handleEvent из базового класса.
Метод handleEvent класса MessageBox
Когда пользователь пытается закрыть окно диалоговой панели, например, сделав двойной щелчок левой клавишей мыши по системному меню или одиночный щелчок по кнопке удаления окна, возникает событие Event.WINDOW_DESTROY. Мы его обрабатываем следующим образом:
if(evt.id == Event.WINDOW_DESTROY)
{
dispose();
return true;
}
else
return super.handleEvent(evt);
Вызывая метод dispose, мы удаляем окно диалоговой панели и освобождаем все связанные с ним ресурсы.
Метод init
Метод init, так же как и метод getAppletInfo, определен в базовом классе Applet, от которого наследуются все аплеты. Определение его таково, что этот метод ровным счетом ничего не делает.
Когда вызывается метод init и зачем он нужен?
Метод init вызывается тогда, когда навигатор Internet загружает в свое окно документ HTML с оператором <APPLET>, ссылающимся на данный аплет. В этот момент аплет может выполнять инициализацию, например, создавать задачи, если он работает в мультизадачном режиме.
Существует контрпара для метода init - метод destroy. О нем мы расскажем немного позже.
Система Java Applet Wizard переопределяет метод init следующим образом:
public void init()
{
resize(320, 240);
// Сделать: Добавьте сюда дополнительный код
// инициализации
}
Здесь вызывается метод resize, который изменяет размер окна аплета. Этот метод определен в базовом классе Applet. В нашем классе вы можете вызывать его потому, что мы образовали этот класс от класса Applet.
Забегая вперед, скажем, что параметры оператора <APPLET>, с помощью которого аплет встраивается в документ HTML, допускают установку размеров окна аплета. Пользуясь методом resize, вы можете изменить эти размеры.
Если же вы желаете изменять размеры окна, редактируя параметры оператора <APPLET> в документе HTML, вы должны удалить вызов метода resize из исходного текста метода init.
Аплет Painter был создан с помощью системы Java Applet Wizard. Мы выполнили изменения методов init, getAppletInfo и paint.
Изменения метода init заключаются в том, что мы закрыли символом комментария строку установки размеров окна аплета:
public void init()
{
// resize(320, 240);
}
Это позволяет задавать размеры окна аплета не в исходном тексте приложения, а в параметрах оператора <APPLET>, с помощью которого аплет встраивается в документ HTML.
Процедура извлечения списка доступных шрифтов, использованная в нашем аплете, достаточно проста и выполняется в методе init, как это показано ниже:
Toolkit toolkit; // ссылка на Toolkit
String fntlist[]; // список шрифтов
. . .
public void init()
{
toolkit = Toolkit.getDefaultToolkit();
fntlist = toolkit.getFontList();
}
Аплет вызывает статический метод getDefaultToolkit из класса Toolkit и затем, пользуясь полученной ссылкой, извлекает список шрифтов, записывая его в массив fntlist.
Для чего еще можно использовать класс Toolkit?
Класс Toolkit является абстрактным суперклассом для всех реализаций AWT. Порожденные от него классы используются для привязки различных компонент конкретных реализаций.
Создавая свои аплеты, вы будете редко прибегать к услугам этого класса. Однако в нем есть несколько полезных методов, прототипы которых мы перечислим ниже:
public abstract class java.awt.Toolkit
extends java.lang.Object
{
// -----------------------------------------------------
// Конструктор
// -----------------------------------------------------
public Toolkit();
// -----------------------------------------------------
// Методы (сокращенный список)
// -----------------------------------------------------
. . .
// Получение ссылки на Toolkit
public static Toolkit getDefaultToolkit();
// Определение текущей цветовой модели,
// выбранной в контекст отображения
public abstract ColorModel getColorModel();
// Получение списка шрифтов, доступных аплету
public abstract String[] getFontList();
// Получение метрик заданного шрифта
public abstract FontMetrics getFontMetrics(Font font);
// Получение растрового изображения по имени файла
public abstract Image getImage(String filename);
// Получение растрового изображения по адресу URL
public abstract Image getImage(URL url);
// Определение разрешения экрана в точках на дюйм
public abstract int getScreenResolution();
// Размеры экрана в пикселах
public abstract Dimension getScreenSize();
// Подготовка растрового изображения для вывода
public abstract boolean
prepareImage(Image image, int width, int height,
ImageObserver observer);
// Синхронизация состояния Toolkit
public abstract void sync();
}
Наиболее интересны, с нашей точки зрения, методы getFontList, getScreenResolution и getScreenSize, с помощью которых аплет может, соответственно, плучить список шрифтов, определить разрешение и размер экрана. Последние два параметра позволяют сформировать содержимое окна аплета оптимальным образом исходя из объема информации, который может в нем разместиться.
При инициализации аплета метод init читает все параметры и записывает их значения в соответствующие поля класса, как это показано ниже:
public void init()
{
String param;
param = getParameter(PARAM_Str1);
if (param != null)
m_Str1 = param;
. . .
param = getParameter(PARAM_Str5);
if (param != null)
m_Str5 = param;
// Шрифты для отображения строк
param = getParameter(PARAM_Font1);
if (param != null)
m_Font1 = param;
. . .
param = getParameter(PARAM_Font5);
if (param != null)
m_Font5 = param;
// Начертание шрифтов
param = getParameter(PARAM_Type1);
if (param != null)
m_Type1 = param;
. . .
param = getParameter(PARAM_Type3);
if (param != null)
m_Type3 = param;
}
Здесь все просто. Метод init по очереди получает значения параметров методом getParameter, которому в качестве параметра передается имя параметра аплета. Полученное значение сохраняется в рабочей переменной param и, если оно отлично от значения null, сохраняется в соответствующем поле класса.
Метод init сбрасывает признак рисования, записывая в поле bDrawing значение false, а также создает новый динамический массив в виде объекта класса Vector:
public void init()
{
bDrawing = false;
lines = new Vector();
}
Этот метод получает контекст отображения, однако не для рисования, а для определения метрик шрифта:
Graphics g = getGraphics();
FontMetrics fm = g.getFontMetrics();
В переменную yHeight заносится полная высота символов текущего шрифта:
yHeight = fm.getHeight();
При инициализации аплета метод init создает четыре кнопки, сохраняя ссылки на них в соответствующих полях нашего класса, а также добавляет эти кнопки в окно аплета, вызывая для этого метод add:
public void init()
{
btn1 = new Button("Button 1");
btn2 = new Button("Button 2");
btn3 = new Button("Button 3");
btn4 = new Button("Button 4");
add(btn1);
add(btn2);
add(btn3);
add(btn4);
sTextLabel = new String("");
}
После добавления кнопок в строку sTextLabel записывается пустое значение, так как ни одна кнопка еще не была нажата.
До сих пор для изменения цвета фона окна наших аплетов мы раскрашивали окно в желтый цвет явным образом в методе paint. Однако есть и другой способ, основанный на вызове метода setBackground:
setBackground(Color.yellow);
Дополнением к этому методу может послужить метод setForeground, с помощью которого можно установить цвет для рисования в окне.
Почему мы выбрали другой способ изменения фона окна?
Дело в том, что переключатели сами по себе являются окнами, обладающими такими атрибутами, как цвет фона и цвет изображения. Если просто нарисовать их в окне, закрашенным желтым цветом, то получится, что серые переключатели нарисованы на желтом фоне, что некрасиво. Метод setBackground, вызванный для окна аплета, позволяет задать цвет фона не только для контейнера, но и для всех компонент, расположенных в нем.
После установки цвета фона метод init создает три переключателя с независимой фиксацией, указывая их название:
chbox1 = new Checkbox("Switch 1");
chbox2 = new Checkbox("Switch 2");
chbox3 = new Checkbox("Switch 3");
Далее метод init создает группу переключателей с зависимой фиксацией в виде объекта класса CheckboxGroup:
grModeGroup = new CheckboxGroup();
Для создания переключателей с зависимой фиксацией необходимо использовать метод, допускающий указание группы и начального состояния переключателя:
rdbox1 = new Checkbox("Mode 1",grModeGroup, true);
rdbox2 = new Checkbox("Mode 2",grModeGroup, false);
rdbox3 = new Checkbox("Mode 3",grModeGroup, false);
rdbox4 = new Checkbox("Mode 4",grModeGroup, false);
Затем метод init создает кнопку с названием Get CheckBoxes state, предназначенную для определения текущего состояния переключателей:
btnGet = new Button("Get CheckBoxes state");
После создания компонент они добавляются в контейнер, которым является окно аплета. Для этого используется метод add.
Прежде всего мы добавляем четыре переключателя с зависимой фиксацией:
add(rdbox1);
add(rdbox2);
add(rdbox3);
add(rdbox4);
Размеры окна и размеры переключателей соотносятся между собой таким образом, что в верхней части окна аплета помещаются как раз четыре переключателя. Очевидно, если изменить размеры окна аплета, переключатели будут размещены по-другому.
Далее метод init добавляет в окно аплета переключатели с независимой фиксацией и кнопку:
add(chbox1);
add(chbox2);
add(chbox3);
add(btnGet);
В методе init мы создаем два списка как объекты класса Choice:
chBackgroundColor = new Choice();
chForegroundColor = new Choice();
Созданные списки пока пустые, но мы можем добавить их в окно аплета, вызвав метод add:
add(chBackgroundColor);
add(chForegroundColor);
Сразу после добавления списков мы их заполняем, вызывая для соответствующих объектов метод addItem:
chBackgroundColor.addItem("Yellow");
chBackgroundColor.addItem("Green");
chBackgroundColor.addItem("White");
chForegroundColor.addItem("Black");
chForegroundColor.addItem("Red");
chForegroundColor.addItem("Blue");
Элементы, добавленные в список первыми, будут выбраны в списке по умолчанию. В нашем случае будет выбран фон желтого цвета и изображение черного цвета.
Такие же цвета мы устанавливаем для окна аплета, вызывая методы setBackground и setForeground:
setBackground(Color.yellow);
setForeground(Color.black);
В методе init мы создаем два списка как объекты класса List:
chBackgroundColor = new List(6, false);
chForegroundColor = new List(4, false);
Первый из этих списков способен одновременно отображать шесть строк, поэтому в нем поместились все шесть цветов для фона. Вертикальный размер второго списка меньше. В результате он снабжается полосой просмотра. Оба списка не предназначены для одновременного выбора нескольких элементов, поэтому в качетсве второго параметра мы передаем конструктору List значение false.
Созданные списки добавляются в окно аплета методом add:
add(chBackgroundColor);
add(chForegroundColor);
Сразу после добавления списков мы их заполняем, вызывая для соответствующих объектов метод addItem:
chBackgroundColor.addItem("Yellow");
chBackgroundColor.addItem("Green");
chBackgroundColor.addItem("White");
chBackgroundColor.addItem("Black");
chBackgroundColor.addItem("Red");
chBackgroundColor.addItem("Blue");
chForegroundColor.addItem("Black");
chForegroundColor.addItem("Red");
chForegroundColor.addItem("Blue");
chForegroundColor.addItem("Yellow");
chForegroundColor.addItem("Green");
chForegroundColor.addItem("White");
Затем метод выбирает для фона желтый цвет, а для изображения - черный:
setBackground(Color.yellow);
setForeground(Color.black);
Метод init создает одно текстовое поле, вызывая конструктор с одним параметром - текстовой строкой:
lbTextLabel = new Label("Выберите выравнивание");
Далее этот метод создает три кнопки, с помощью которых вы будете изменять выравнивание текста в поле класса Label:
btnLeft = new Button("Влево");
btnCenter = new Button("Центровка");
btnRight = new Button("Вправо");
Затем созданные кнопки и поле добавляются в окно аплета при помощи метода add:
add(btnLeft);
add(btnCenter);
add(btnRight);
add(lbTextLabel);
Последнее, что делает метод init перед возвращением управления, это изменение цвета фона:
setBackground(Color.yellow);
Метод init создает одно текстовое поле редактирования, вызывая конструктор с параметром в виде текстовой строки:
txt = new TextField("Введите строку текста", 35);
Далее этот метод создает кнопку, с помощью которой можно получить текущее содержимое поля редактирования:
btnGetText = new Button("Получить строку");
Затем созданные поле и кнопка добавляются в окно аплета при помощи метода add:
add(txt);
add(btnGetText);
После этого метод init получает текущее содержимое поля редактирования и записывает его в строку str:
str = txt.getText();
В завершении метод init изменяет цвет фона:
setBackground(Color.yellow);
Метод init создает одно текстовое поле редактирования, вызывая конструктор следующего вида:
txt = new TextArea("Введите строку текста", 5, 35);
Здесь создается поле из 5 строк и 35 столбцов.
Далее этот метод создает кнопки, с помощью которых можно получить текущее содержимое всего поля редактирования и области, выделенной пользователем:
btnGetText = new Button("Получить все");
btnGetSelectedText = new Button("Получить выделенное");
Затем созданные поле и кнопки добавляются в окно аплета при помощи метода add:
add(txt);
add(btnGetText);
add(btnGetSelectedText);
После этого метод init получает текущее содержимое поля редактирования и записывает его в строку str, а затем изменяет цвет фона:
str = txt.getText();
setBackground(Color.yellow);
Метод init создает все необходимые панели и добавляет в них компоненты.
В самом начале своей работы метод init устанавливает желтый цвет фона для окна аплета:
setBackground(Color.yellow);
После этого выбирается такой режим размещения компонентов, при котором они добавляются в таблицу, состоящую из двух строк и одного столбца:
setLayout(new GridLayout(2, 1));
Мы будем добавлять панели, поэтому первая из добавленных панелей окажется в верхней строке этой таблицы и займет верхнюю половину окна аплета, а вторая - нижнюю.
Далее метод init создает пять кнопок, которые будут добавлены на страницы блокнота, расположенного в верхней панели:
btn1 = new Button("Button 1");
btn2 = new Button("Button 2");
btn3 = new Button("Button 3");
btn4 = new Button("Button 4");
btn5 = new Button("Button 5");
После создания кнопок метод init приступает к созданию и заполнению панели блокнота. Панель создается при помощи конструктора класса Panel:
pCardPanel = new Panel();
Для этой панели устанавливается режим размещения компонент типа CardLayout, причем между границами окна панели и границами окна добавляемых компонент по вертикали и горизонтали оставлен зазор 5 пикселов:
pCardPanel.setLayout(new CardLayout(5, 5));
После установки режима добавления можно заполнять блокнот кнопками:
pCardPanel.add(btn1);
pCardPanel.add(btn2);
pCardPanel.add(btn3);
pCardPanel.add(btn4);
pCardPanel.add(btn5);
Здесь мы воспользовались известным вам методом add, вызвав его для объекта pCardPanel.
Заполненная панель блокнота при помощи все того же метода add добавляется в окно аплета:
add(pCardPanel);
Так как эта панель добавляется в окно аплета первой, она займет верхнюю половину этого окна.
Завершив с панелью блокнота, метод init приступает к формированию панели управляющих кнопок.
Вначале метод создает сами управляющие кнопки:
btnNext = new Button("Next");
btnPrev = new Button("Prev");
Первая из них перелистывает страницы блокнота в прямом направлении, а вторая - в обратном.
Затем создается панель кнопок:
pButtonPanel = new Panel();
Для панели кнопок мы выбираем режим выравнивания FlowLayout, при котором компоненты добавляются слева направо и сверху вниз:
pButtonPanel.setLayout(new FlowLayout());
После этого в панель добавляются две управляющие кнопки, преднаазначенные для перелистывания страниц блокнота:
pButtonPanel.add(btnNext);
pButtonPanel.add(btnPrev);
На завершающем этапе своей работы метод init добавляет панель управляющих кнопок в окно аплета:
add(pButtonPanel);
Данная панель добавляется в окно аплета второй по счету, поэтому она будет расположена в нижней половине этого окна.
Метод init выполняет достаточно громоздкую работу по созданию и добавлению различных панелей и других компонентов. К сожалению, приложениям Java не доступны ресурсы, аналогичные ресурсам операционной системы Microsoft Windows, поэтому формирование диалоговых панелей и других элементов пользовательского интерфейса приходится выполнять чисто программными методами на этапе выполнения приложения. Средства среды разработки приложений Java Microsoft Visual J++ версии 1.1, о которых мы уже упоминали, позволяют несколько упростить этот процесс.
Свою работу метод init начинает с установки желтого цвета фона для окна аплета.
Далее устанавливается режим добавления GridLayout, разделяющий окно аплета на три части по горизонтали:
setLayout(new GridLayout(3, 1));
Соответствующая таблица, в которую будут добавляться компоненты, имеет три строки и один столбец.
Панель блокнота создается следующим образом:
pCardPanel = new Panel();
Затем создаются три панели, которые будут добавляться в панель pCardPanel:
pBackgroundColor = new Panel();
pForegroundColor = new Panel();
pFont = new Panel();
Эти панели предназначены для размещения компонент, с помощью которых можно будет выбирать цвет фона и изображения, а также шрифт.
На следующем этапе создаются три списка, которые будут размещаться по одному на указанных панелях:
chBackgroundColor = new Choice();
chForegroundColor = new Choice();
chFont = new Choice();
Каждый такой список снабжается надписью, поясняющей его назначение. Надписи создаются следующим образом:
tBackgroundColor = new Label("Chose Background Color:");
tForegroundColor = new Label("Chose Foreground Color:");
tFont = new Label("Chose Font:");
Созданные метки и списки добавляются в панели, расположенные на страницах блокнота:
pBackgroundColor.add(tBackgroundColor);
pBackgroundColor.add(chBackgroundColor);
pForegroundColor.add(tForegroundColor);
pForegroundColor.add(chForegroundColor);
pFont.add(tFont);
pFont.add(chFont);
Метод init класса FrameWnd
В процессе инициализации аплета метод init создает объект класса MainFrameWnd - перекрывающееся окно с заголовком "Main Frame Window":
fMainFrame = new MainFrameWnd("Main Frame Window");
Для этого вызывается конструктор из класса MainFrameWnd, созданного нами на базе класса Frame.
После этого метод init создает две кнопки и добавляет их в окно аплета:
btnShowFrame = new Button("Show Frame Window");
add(btnShowFrame);
btnHideFrame = new Button("Hide Frame Window");
add(btnHideFrame);
Первая из этих кнопок предназначена для отображения перекрывающегося окна, а вторая - для временного удаления или скрытия этого окна.
Прежде всего метод init устанавливает для окна панели режим добавления компонент GridLayout, определяя таблицу из двух строк и одного столбца.
Первая панель создается на базе класса FirstPanel, определенного в нашем приложении:
pPanel1 = new FirstPanel();
Этот класс мы рассмотрим позже.
Созданная панель добавляется в окно аплета методом add:
add(pPanel1);
Аналогично мы создаем и вторую панель, на этот раз как объект класса SecondPanel:
pPanel2 = new SecondPanel();
Вторая панель добавляется в окно аплета точно также, как и первая:
add(pPanel2);
Для того чтобы выделить панели на фоне окна аплета, мы устанавливаем для них разные цвета фона и изображения. Для первой панели устанавливается желтый цвет фона и черный цвет изображения:
pPanel1.setBackground(Color.yellow);
pPanel1.setForeground(Color.black);
Для второй панели мы устанавливаем белый цвет фона и красный цвет изображения:
pPanel2.setBackground(Color.white);
pPanel2.setForeground(Color.red);
В результате цвета рамки окна и текста первой и второй панели будут разными.
На последнем этапе инициализации мы инициируем вызов метода paint класса Panel2, вызывая для этого метод repaint:
repaint();
Это нужно для того, чтобы сразу после отображения окна аплета выполнить рисование текстовых строк внутри окон панелей.
Метод keyDown
Когда пользователь нажимает клавишу, управление передается методу keyDown. Обработчик метода keyDown преобразует код нажатой клавиши nKey в текстовую строку типа String и затем отображает эту строку и содержимое двух полей объекта evt в окне аплета.
Преобразование выполняется в два приема.
Вначале код символа, имеющий тип int, преобразуется к типу char и записывается в ячейку массива типа char[], как это показано ниже:
char[] chKey;
String s;
chKey = new char[1];
chKey[0] = (char)nKey;
Затем этот массив, состоящий только из одного элемента, преобразуется в текстовую строку:
s = new String(chKey);
Далее метод ketDown получает контекст отображения, устанавливает в нем черный цвет и рисует в верхней части окна параметры клавиатурного события:
Graphics g = getGraphics();
g.setColor(Color.black);
g.drawString(s + " ", 10, 10);
g.drawString(" -> key: " + evt.key, 20, 10);
g.drawString(" mod: " + evt.modifiers, 100, 10);
Метод keyUp
Метод keyUp получает управление, когда пользователь отпускает ранее нажатую клавишу. Ему передаются те же параметры, что и только что рассмотренному методу keyDown.
Наш метод keyUp получает контекст отображения, а затем выполняет копирование верхней части окна, сдвигая ее вниз на размер символов текущего шрифта:
g.copyArea(0, 1,
dimAppWndDimension.width - 1,
dimAppWndDimension.height - yHeight - 5,
0, yHeight + 1);
После сдвига метод закрашивает область ввода, расположенную в верхней части аплета, желтым цветом, расчищая таким образом место для ввода новой строки:
g.setColor(Color.yellow);
g.fillRect(1, 1,
dimAppWndDimension.width - 2, yHeight + 1);
Метод mouseDown
Когда пользователь делает щелчок левой клавишей мыши (напомним, что Java не работает с другими клавишами мыши), управление получает метод mouseDown.
Этот метод, переопределенный в нашем приложении, прежде всего сохраняет текущие координаты курсора мыши в переменной dimMouseCursor класса Dimension:
dimMouseCursor = new Dimension(x, y);
Событие, которое передается методу mouseDown через первый параметр, сохраняется в переменной ev:
ev = evt;
Далее метод mouseDown проверяет поле clickCount параметра evt:
if(evt.clickCount > 1)
showStatus("Mouse Double Click");
else
showStatus("Mouse Down");
В это поле записывается кратность щелчка мыши. Если пользователь сделал двойной щелчок, в строке состояния отображается текстовая строка Mouse Double Click, а если одинарный - строка Mouse Down.
Обратите внимание на метод showStatus. Этот метод позволяет аплету отобразить любую текстовую строку в строке состояния навигатора, поэтому он часто используется для отладки или выдачи текущей информации о состоянии аплета.
Заметим, однако, что в документе HTML может располагаться несколько разных аплетов, а строка состояния навигатора только одна. Поэтому сообщения от разных аплетов могут перекрывать друг друга, в результате чего в строке состояния появится только то сообщение, которое было записано туда последним.
После записи сообщения в строку состояния метод mouseDown перерисывывает окно аплета, вызывая для этого метод repaint:
repaint();
В результате вызова метода repaint происходит инициирование вызова метода paint, выполняющего перерисовку содержимого окна аплета. Однако не следует думать, будто метод repaint просто вызывает метод paint. Метод paint вызывается интерпретатором Java асинхронно по отношению к методу repaint в подходящий момент времени.
В последней строке метод mouseDown возвращает значение true:
return true;
Этим он сообщает, что обработка события завершена и это событие не нужно передавать обработчику из базового класса.
В начале своей работы метод mouseDown определяет, был ли сделан одинарный щелчок клавишей мыши, или двойной. Если был сделан двойной щелчок мышью, метод удаляет все элементы из массива list, а затем перерисовывает окно аплета, вызывая метод repaint:
lines.removeAllElements();
repaint();
После перерисовки окно аплета очищается от линий.
Если же был сделан одинарный щелчок клавишей мыши, метод mouseDown сохраняет текущие координаты курсора в переменных dmDown и dmPrev, а затем сбрасывает признак рисования:
dmDown = new Dimension(x, y);
dmPrev = new Dimension(x, y);
bDrawing = false;
Метод mouseDrag
До сих пор наши аплеты выполняли рисование только в методе paint, и так поступают большинство аплетов. Однако наш аплет должен рисовать линии во время перемещения курсора мыши, так как в противном случае пользователю не будет видно, как пройдет рисуемая линия.
Для того чтобы нарисовать что-либо в окне аплета, наобходимо получить контекст отображения. Методу paint этот контекст передается через парметр как объект класса Graphics. Если же вы собираетесь рисовать в другом методе, отличном от paint, необходимо получить контекст отображения, например, так:
Graphics g = getGraphics();
После получения контекста отображения и включения режима рисования (записью в переменную bDrawing значения true) метод mouseDrag стирает линию, которая была нарисована ранее, в процессе предыдущего вызова этого же метода:
g.setColor(Color.yellow);
g.drawLine(dmDown.width, dmDown.height,
dmPrev.width, dmPrev.height);
Для стирания линии мы рисуем ее на том же месте с использованием цвета, совпадающего с цветом фона.
Далее метод mouseDrag рисует новую линию черного цвета, соединяя точку, в которой была нажата клавиша мыши, с точкой текущего расположения курсора мыши:
g.setColor(Color.black);
g.drawLine(dmDown.width, dmDown.height, x, y);
После рисования линии координаты ее конца сохраняются в поле dmPrev для стирания этой линии при следующем вызове метода mouseDrag:
dmPrev = new Dimension(x, y);
return true;
Метод mouseMove
Метод mouseMove выглядит следующим образом:
public boolean mouseMove(Event evt, int x, int y)
{
return true;
}
Он ничего не делает, кроме того что возвращает значение true, блокируя обработку события, выполняемую в базовом классе.
Метод mouseMove не делает ничего, за исключением того, что он отключает режим рисования. Таким образом, простое перемещение курсора мыши над окном аплета не приводит к рисованию линий.
Метод mouseUp
Когда пользователь отпускает клавишу мыши, вызывается метод mouseUp. В его задачу входит сохранение текущих координат курсора мыши в поле dmUp, а также добавление нового элемента в массив lines, как это показано ниже:
dmUp = new Dimension(x, y);
lines.addElement(
new Rectangle(dmDown.width, dmDown.height, x, y));
repaint();
После добавления элемента в массив метод mouseUp инициирует перерисовку окна аплета, вызывая для этого метод repaint.
Заметим, что в качестве координат начала линии мы записываем в элемент массива координаты точки, где в последний раз пользователь нажимал курсор мыши. В качестве координат конца линии используются текущие координаты курсора на момент отпускания клавиши мыши.
Метод 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);
Метод paint класса FirstPanel
Задачей метода paint класса FirstPanel является рисование рамки вокруг первой панели и текстовой строки в окне этой панели. В качестве параметра метод paint класса FirstPanel получает ссылку на контекст отображения для окна первой панели. Мы можем использовать этот контекст для того чтобы нарисовать что-нибудь внутри первой панели.
Процедура рисования не имеет никаких особенностей:
Dimension dimAppWndDimension = size();
g.drawRect(0, 0, dimAppWndDimension.width - 1,
dimAppWndDimension.height - 1);
g.setFont(new Font("TimesRoman", Font.PLAIN, 12));
g.drawString("Первая панель", 10, 50);
Заметим, однако, что после завершения рисования мы вызываем метод paint из базового класса, позволяя этому классу выполнить свою обработку:
super.paint(g);
Метод paint класса MainFrameWnd
Метод paint получает в качестве параметра ссылку на контекст отображения, пригодный для рисования в нашем окне. Пользуясь этим контекстом, мы устанавливаем шрифт текста и рисуем текстовую строку. Затем мы вызываем метод paint из базового класса Frame, на основе которого создан наш класс MainFrameWnd:
g.setFont(new Font("Helvetica", Font.PLAIN, 12));
g.drawString("Окно класса Frame", 10, 50);
super.paint(g);
Метод paint класса SecondPanel
Метода paint класса SecondPanel выполняет те же самые операции, что и метод paint класса FirstPanel, однако ему передается контекст отображения второй панели. Поэтому он нарисует рамку и текстовую строку во второй панели, а не в первой или где-нибудь еще.
Метод start
Метод start вызывается после метода init в момент, когда пользователь начинает просматривать документ HTML с встроенным в него аплетом. Система Java Applet Wizard создает заглушку, переопределяющую метод start из базового класса:
public void start()
{
// Сделать: Добавьте сюда дополнительный код,
// который должен работать при запуске аплета
}
Вы можете модифицировать текст этого метода, если при каждом посещении пользователем страницы с аплетом необходимо выполнять какую-либо инициализацию.
Метод stop
Дополнением к методу start служит метод stop. Он вызывается, когда пользователь покидает страницу с аплетом и загружает в окно навигатора другую страницу. Заметим, что метод stop вызывается перед методом destroy.
По умолчанию система Java Applet Wizard переопределяет метод stop базового класса Applet следующим образом:
public void stop()
{
// Сделать: Добавьте сюда дополнительный код,
// который должен работать при остановке аплета
}
Методы класса Graphics
В качестве базового для класса Graphics (полное название класса java.awt.Graphics) выступает классс java.lang.Object. В виду важности класса Graphics мы приведем его определение с комментариями:
public abstract class java.awt.Graphics
extends java.lang.Object
{
// -----------------------------------------------------
// Конструктор
// -----------------------------------------------------
protected Graphics();
// -----------------------------------------------------
// Методы
// -----------------------------------------------------
// Стирание содержимого прямоугольной области
public abstract void
clearRect(int x, int y, int width, int height);
// Задание области ограничения вывода
public abstract void
clipRect(int x, int y, int width, int height);
// Копирование содержимого прямоугольной области
public abstract void
copyArea(int x, int y, int width,
int height, int dx, int dy);
// Создание контекста отображения
public abstract Graphics create();
// Создание контекста отображения
public Graphics create(int x, int y,
int width, int height);
// Удаление контекста отображения
public abstract void dispose();
// Рисование прямоугольной области с трехмерным
// выделением
public void draw3DRect(int x, int y, int width,
int height, boolean raised);
// Рисование сегмента
public abstract void drawArc(int x, int y,
int width, int height, int startAngle, int arcAngle);
// Рисование текста из массива байт
public void drawBytes(byte data[], int offset,
int length, int x, int y);
// Рисование текста из массива символов
public void drawChars(char data[], int offset,
int length, int x, int y);
// Рисование растрового изображения
public abstract boolean
drawImage(Image img, int x, int y, Color bgcolor,
ImageObserver observer);
// Рисование растрового изображения
public abstract boolean
drawImage( Image img, int x, int y,
ImageObserver observer);
// Рисование растрового изображения
public abstract boolean
drawImage(Image img, int x, int y,
int width, int height, Color bgcolor,
ImageObserver observer);
// Рисование растрового изображения
public abstract boolean
drawImage(Image img, int x, int y,
int width, int height, ImageObserver observer);
// Рисование линии
public abstract void drawLine(int x1, int y1,
int x2, int y2);
// Рисование овала
public abstract void drawOval(int x, int y,
int width, int height);
// Рисование многоугольника
public abstract void
drawPolygon(int xPoints[], int yPoints[], int nPoints);
// Рисование многоугольника
public void drawPolygon(Polygon p);
// Рисование прямоугольника
public void drawRect(int x, int y,
int width, int height);
// Рисование прямоугольника с круглыми углами
public abstract void
drawRoundRect(int x, int y, int width,
int height, int arcWidth, int arcHeight);
// Рисование текстовой строки
public abstract void
drawString(String str, int x, int y);
// Рисование заполненного прямоугольника с
// трехмерным выделением
public void
fill3DRect(int x, int y, int width,
int height, boolean raised);
// Рисование заполненного сегмента круга
public abstract void
fillArc(int x, int y, int width,
int height, int startAngle, int arcAngle);
// Рисование заполненного овала
public abstract void
fillOval(int x, int y, int width, int height);
// Рисование заполненного многоугольника
public abstract void
fillPolygon(int xPoints[], int yPoints[], int nPoints);
// Рисование заполненного многоугольника
public void fillPolygon(Polygon p);
// Рисование заполненного прямоугольника
public abstract void
fillRect( int x, int y, int width, int height);
// Рисование заполненного прямоугольника
// с круглыми углами
public abstract void
fillRoundRect(int x, int y, int width, int height,
int arcWidth, int arcHeight);
// Прослеживание вызова метода dispose
public void finalize();
// Определение границ области ограничения вывода
public abstract Rectangle getClipRect();
// Определение цвета, выбранного в контекст отображения
public abstract Color getColor();
// Определение шрифта, выбранного в контекст отображения
public abstract Font getFont();
// Определение метрик текущего шрифта
public FontMetrics getFontMetrics();
// Определение метрик заданного шрифта
public abstract FontMetrics getFontMetrics(Font f);
// Установка цвета для рисования в контексте отображения
public abstract void setColor(Color c);
// Установка текущего шрифта в контексте отображения
public abstract void setFont(Font font);
// Установка режима рисования
public abstract void setPaintMode();
// Установка маски для рисования
public abstract void setXORMode(Color c1);
// Получение текстовой строки, представляющей
// данный контекст отображения
public String toString();
// Сдвиг начала системы координат
// в контексте отображения
public abstract void translate(int x, int y);
}
Рассмотрим назначение основных методов, сгруппировав их по выполняемым функциям.
Методы mouseUp, mouseDrag, mouseEnter, mouseExit
Обработчики методов mouseUp, mouseDrag, mouseEnter и mouseExit выглядят одинаково:
public boolean mouseUp(Event evt, int x, int y)
{
// Выводим сообщение в строке состояния
showStatus("Mouse Up");
return true;
}
Пользуясь методом showStatus, эти методы записывают соответствующее сообщение в строку состояния и возвращают значение true.
Многострочное текстовое поле класса TextArea
Если вам нужно поле для ввода многострочной информации, обратите внимание на класс TextArea. С его помощью вы можете создать многострочное поле заданной ширины и высоты, снабженное полосами просмотра.
Класс TextArea создан на базе класса TextComponent, рассмотренном нами ранее, поэтому для работы с многострочными полями вы можете использовать методы этого класса. В частности, вам доступен метод, с помощью которого можно получать из онка редактирования не весь текст, а только выделенную пользователем область.
Краткое описание класса TextArea мы привели ниже:
public class java.awt.TextArea
extends java.awt.TextComponent
{
// -----------------------------------------------------
// Конструкторы
// -----------------------------------------------------
// Создание поля без текста и без указания размеров
public TextArea();
// Создание поля без текста с указанием размеров
public TextArea(int rows, int cols);
// Создание поля с текстом без указания размеров
public TextArea(String text);
// Создание поля с текстом и с указанием размеров
public TextArea(String text, int rows, int cols);
// -----------------------------------------------------
// Методы
// -----------------------------------------------------
// Вызов метода createTextArea
public void addNotify();
// Добавление текста в поле редактирования
public void appendText(String str);
// Определение количества столбцов поля
public int getColumns();
// Определение количества строк поля
public int getRows();
// Добавление текста в поле редактирования
// начиная с заданной позиции
public void insertText(String str, int pos);
// Определение минимальных размеров области
// для размещения многострочного текстового поля
public Dimension minimumSize();
// Определение минимальных размеров области
// для размещения многострочного текстового поля
// с заданным количеством строк и столбцов
public Dimension minimumSize(int rows, int cols);
// Получение строки параметров
protected String paramString();
// Определение предпочтительных размеров области
// для размещения многострочного текстового поля
public Dimension preferredSize();
// Определение предпочтительных размеров области
// для размещения многострочного текстового поля
// с заданным количеством строк и столбцов
public Dimension preferredSize(int rows, int cols);
// Замещение блока текста, начиная с первой позиции
// и до второй позиции
public void replaceText( String str, int start, int end);
}
Когда вы создаете многострочное текстовое поле редактирования, то можете использовать конструктор, допускающий указание размеров поля в строках и столбцах:
TextArea txt;
txt = new TextArea("Введите строку текста", 5, 35);
Созданное поле добавляется в окно аплета методом add.
Отметим, что в классе TextArea есть методы для работы с блоками текста (вставка и замена), а также методы, с помощью которых можно определить количество строк и столбцов в поле редактирования.