
- •Программирование в графических операционных системах Методические указания к лабораторным работам
- •Лабораторная работа №1
- •Предварительные сведения
- •Лабораторная работа №2
- •Лабораторная работа №3
- •Лабораторная работа №4
- •Лабораторная работа №5
- •Лабораторная работа №6
- •Лабораторная работа №7
- •Лабораторная работа №8
- •Лабораторная работа №9
- •Библиографический список
Лабораторная работа №3
Содержание работы. Ознакомление со строением программы графического приложения средствами Abstract Window Toolkit языка Java.
Предварительные сведения
Для современных приложений Java в классах графических компонентов специальными конструкциями задается заинтересованность отдельных частей приложения в конкретных типах событий. Такие конструкции могут иметь один из двух вариантов построения. Первый вариант представляет собой директиву добавления в специальный внутренний список компонента, причем добавляются сведения о блоке прослушивания (listener). Сама директива имеет при этом на языке Java общий вид
обозначение_компонента.addТип_событияListener(new
Тип_событияListener(){
описание переопределяемых методов базового блока прослушивания
});
Это описание вводит так называемый анонимный внутренний класс, содержимое которого определяется тут же при его создании конструктором. В данном случае это содержимое представляется для адаптера описанием переопределяемых методов базового блока прослушивания. Блок прослушивания, обозначаемый как Тип_событияListener, представляет собой в терминах Java, интерфейс, что обозначает по существу описание всего лишь заготовки класса, аналогичной по смыслу абстрактному классу в языке C++.
Второй вариант конструкции имеет более явное строение и состоит из двух частей. В первой из них также описывается добавление блока прослушивания к специальному списку компонента, но в аргументе директивы добавления задается не новый блок прослушивания, а новый адаптер событий. Эта часть конструкции имеет общий вид
обозначение_компонента.addТип_событияListener(new
Новый_адаптер_события());
Отдельно от этой части описывается сам новый адаптер событий, который представляет собой целый класс, но вложенный в компонент, использующий этот адаптер. Такое описание имеет вид
class Новый_адаптер_события extends Тип_событияAdapter {
переопределение методов базового адаптера типа событий }
Для принятия решения, какой из вариантов использовать, следует учитывать, что при создании нового блока прослушивания в первом варианте необходимо реализовать каждый из методов базового (стандартного) блока прослушивания. Такая необходимость вытекает из того, что стандартные блоки прослушивания Тип_событияListener являются интерфейсами, т. е. предварительными описаниями, которые содержат только прототипы методов, но не их реализации. Поэтому для тех типов событий, стандартные блоки прослушивания которых содержат более одного метода, предпочтительней оказывается использование соответствующих адаптеров. Стандартные адаптеры типа события являются не интерфейсами, а полноценными классами, поэтому достаточно переопределить в них только те методы, для которых разработчик желает иметь нестандартную реакцию его компонента на соответствующее событие.
Для выбора варианта рекомендуется внимательно познакомиться с документацией на конкретный тип события. Если стандартный тип события содержит только один стандартный метод его обработки, то практичней использовать непосредственную собственную реализацию блока прослушивания (первый вариант), в ином случае проще описать новый адаптер типа события (второй вариант).
В представленных общих формах конструкций для добавления блока прослушивания, начальный элемент конструкции обозначение_компонента может быть опущен вместе с последующей точкой, если таким компонентом является собственно класс, в котором использовано такое описание (вместо того, чтобы избыточно записать this.).
Все события в современной реализации Java разделяются на два типа: низкоуровневые и высокоуровневые. Классы этих событий являются производными от абстрактного класса java.awt.AWTEvent. Низкоуровневые события связаны с физическими аспектами технического интерфейса пользователя. Это щелчки мыши, нажатия клавиш клавиатуры, сигналы от перемещения мыши и т. п. Семантические события строятся на основе низкоуровневых событий. Характерным примером семантического события является выбор команды меню (который в действительности может быть порожден либо щелчком мыши, либо воздействием нажатия на клавишу клавиатуры).
Все низкоуровневые события являются подклассами класса ComponentEvent. Это классы ContainerEvent, FocusEvent, InputEvent и WindowEvent. Класс InputEvent включает дополнительные подклассы KeyEvent и MouseEvent. Событие ContainerEvent как экземпляр одноименного класса возникает всякий раз, когда графический компонент добавляется или удаляется из контейнера. Событие FocusEvent как экземпляр одноименного класса возникает, когда компонент получает или теряет фокус ввода. Событие WindowEvent как экземпляр класса возникает, когда пользователь воспользуется одной из кнопок системного меню или кнопками управления окна (минимизации, максимизации или закрытия окна). Дополнительно к перечисленным низкоуровневым событиям класс ComponentEvent включает специальный тип события PaintEvent, которое не используется в модели делегирования событий. Использование этого события мы рассмотрим позже.
К семантическим событиям относятся ActionEvent, AdjustmentEvent, ItemEvent и TextEvent. Событие ActionEvent уведомляет приложение о выполнении специфического действия, связанного с компонентом (например, щелчок мыши на визуальной кнопке). Событие AdjustmentEvent информирует о перемещении ползунка полосы прокрутки, событие ItemEvent уведомляет, что пользователь изменил состояние переключателя, списка или флажка опции. Событие TextEvent возникает как результат изменения текста в компонентах типа TextArea или TextField.
Рассмотрим применение описанной модели делегирования событий для решения той же прикладной задачи, которая решалась в предыдущем разделе. Реализация простейшего оконного приложения с выдачей сообщений о щелчках мыши в области окна приложения приведена следующим текстом программы.
import java.awt.*;
import java.awt.event.*;
public class simple {
public static void main(String args[]){
Frame window=new MyFrame("Our second Java Frame!");
window.setSize(300,200);
window.show();
}
}// end class simple
class MyFrame extends Frame {
MessageBox mbox;
MyFrame frame;
public MyFrame(String title) {
super(title);
addWindowListener(new MyWindowAdapter());
addMouseListener(new MyMouseAdapter());
frame=this;
}
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent ev){
dispose(); System.exit(0);
}
} //end inner class MyWindowAdapter
class MyMouseAdapter extends MouseAdapter{
String mes;
public void mousePressed(MouseEvent ev){
if (ev.getModifiers()==MouseEvent.BUTTON1_MASK)
mes="left";
else mes="right";
mbox=new MessageBox(frame, "Press "+mes+" button", "Message");
mbox.show();
}
} // end inner class MyMouseAdapter
}
В начале исходных текстов Java программ записываются подключение базовых пакетов, необходимых для трансляции программ. Эти действия задаются операторами import и содержат перечисление либо отдельных компонентов пакетов, либо подключение всего содержимого этих пакетов. В последнем случае вместо наименования отдельных классов применяется метасимвол *.
Указание заинтересованности главного графического компонента окна, описываемого классом MyFrame, задается фрагментом
addWindowListener(new MyWindowAdapter());
addMouseListener(new MyMouseAdapter());
frame=this;
Новый адаптер MyWindowAdapter для индивидуальной обработки событий закрытия окна строится на основе стандартного адаптера WindowAdapter и переопределяет метод windowClosing этого класса. Переопределение заключается в выполнении метода уничтожения ресурсов главного окна приложения и завершения методом exit программы приложения.
Новый адаптер MyMouseAdapter строится на основе стандартного адаптера MouseAdapter, предназначенного для обработки событий от мыши, и переопределяет один из методов последнего, а именно, метод mousePressed. Переопределенный метод вызывается при нажатии кнопки мыши. Информация, какая именно кнопка мыши нажата, получается от метода getModifiers(), который возвращает содержимое специального внутреннего поля modifiers событий Event. Для событий от мыши значения этого поля дают информации о нажатой кнопке. Такая информация представляется константами BUTTON1_MASK и BUTTON2_MASK, определенными в классе MouseEvent. Для вспомогательных целей класс адаптера MyMouseAdapter использует переменную строкового типа mes, в которую на основе анализа поля modifiers заносится текст, идентифицирующий правую или левую кнопку мыши.
Достаточно универсальный класс MessageBox блока сообщений для рассмотренной программы может быть использован готовый, когда он присутствует в учебной установке системы Java для данного учебного курса на соответствующих компьютерах учебной лаборатории. При отсутствии такой заготовки можно использовать исходный текст этого класса, приведенный следующим текстом
import java.awt.*;
import java.awt.event.*;
public class MessageBox extends Dialog {
Label label;
Button btn;
Point posParent;
int boxHeight, boxWidth;
int parentHeight, parentWidth;
class MyWindowAdapter extends WindowAdapter {
public void windowClosing(WindowEvent ev){
dispose();
}
}
public MessageBox(Frame parent, String sMsg, String title){
super(parent, title);
posParent=parent.getLocation();
parentHeight=parent.getHeight(); parentWidth=parent.getWidth();
setLayout(new GridLayout(2,1));
label=new Label(sMsg, Label.CENTER);
add(label);
btn=new Button("OK");
add(btn);
pack();
boxHeight=getHeight(); boxWidth=getWidth();
setLocation(posParent.x+parentWidth/2-boxWidth/2,
posParent.y+parentHeight/2-boxWidth/2);
addWindowListener(new MyWindowAdapter());
btn.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ev) {
if (btn.getLabel()=="OK") dispose();
}
});
}
}
При разработке программ в базовой инструментальной системе JDK для трансляции программы из исходного текста в байт код применяется транслятор, имеющий имя javac. При его использовании необходимо иметь в виду, что обрабатываемый исходный файл должен быть указан при вызове транслятора полностью, включая и расширение, которое обязательно должно быть стандартным — java. Попытка запуска транслятора только с собственным именем исходного файла выливается в сообщения от транслятора, которые не всегда могут быть легко поняты начинающим программистом. Таким образом, если исходный файл программы имеет имя prog.java, то запуск его на трансляцию имеет вид
javac prog.java
В результате трансляции образуется один или несколько файлов байт кода java, которые имеют расширение class.
Для запуска java приложения, программные части которого в виде байт кодов готовы к выполнению и находятся в текущем каталоге (или каталогах, к которым обеспечивается автоматический доступ соответствующими установками вспомогательной информации) требуется запустить на выполнение интерпретатор, передав ему в качестве параметра запуска собственное имя основного файла приложения, имеющего расширение class, но само расширение в указываемом параметре запуска не указывается. Так, для запуска на выполнение java программы, которая строилась из исходного файла prog.java, необходимо выполнить команду
java prog
На самом деле при этом запускается на выполнение файл с именем prog.class. Аналогично трансляции, неправильное использование расширения файла при запуске на выполнение приводит к возникновению ошибки запуска и соответствующим сообщениям об такой ошибке в терминах технической документации.
Использование в разработке методов и констант, требуемых в применяемых базовых классах, влечет для программиста необходимость активного общения с технической документацией на систему программирования. Для Java этот пакет поставляется в форматах html и организован в виде иерархической структуры. Обычно в главной каталоге этого пакета с именем docs присутствуют подкаталоги api, guide, images, relnotes, tooldocs и стартовый файл индекса index.html. В процессе лабораторных работ по изучаемой дисциплине будет достаточно сразу же обратиться к подкаталогу java каталога api в этом перечне. Остальные и очень объемные части документации относятся к более широким или более прикладным вопросам, а также к пакетам множества современных расширений Java. В каталоге java, в свою очередь, основной интерес для темы лабораторных работ представляет документация в его подкаталоге с именем awt. Внутри последнего каталога понадобится также и содержимое подкаталога event.
При выполнении данной лабораторной работы особое внимание следует уделить содержимому класса KeyListener, описанному в файле KeyListener.html, и содержимому класса KeyEvent.
Задание. Разработать в среде разработки Java простейшее графическое приложение на основе класса Frame и вспомогательного класса MessageBox, которое использует расширение класса MouseAdapter c методом mousePressed и методом getModifiers, а также обеспечивает отображение информации от воздействия на клавиатуру с сообщением, какая клавиша нажата (использовать прослушиватель событий от клавиатуры). При воздействии от клавиатуры должна отображаться содержательная информация как при нажатии алфавитно-цифровой клавиши, так и при нажатии управляющей клавиши.
Контрольные вопросы
1. Каким образом связаны события окружающего мира, внешнего к программе Java, и запуск на выполнение методов обработки событий mousePressed() и windowClosing()?
2. Почему перед записью вызова на выполнение метода getModifiers() необходимо использовать квалификатор?
3. Когда в записи вызова метода класса на выполнение нет необходимости указывать квалификатор?