Событием в языке Java является объект. Все события можно разделить на две группы: события низкого уровня и семантические события.
К событиям низкого уровня относятся:
Семантические события являются событиями верхнего уровня и зависят от инициировавшего их компонента. Одно и то же семантическое событие может быть инициировано разными компонентами в ответ на различные действия пользователя. Семантическое событие можно рассматривать как более сложное событие, состоящее из одного или нескольких событий низкого уровня. Примером может служить событие MenuEvent, инициируемое при выборе пункта меню.
В настоящее время в языке Java используется модель ожидаемых событий. В этой модели инициируются только те события, которые были объявлены объектами как ожидаемые.
Объект регистрирует блок прослушивания событий. Блок прослушивания - это интерфейс, который определяет набор методов-обработчиков событий, объявленных как ожидаемые события.
Регистрация блока прослушивания для компонента состоит в вызове метода, начинающегося с префикса add, за которым идет имя блока прослушивания. Имена блоков прослушивания оканчиваются суффиксом Listener.
Для одного компонента можно зарегистрировать только один блок прослушивания. Но один блок прослушивания может использоваться несколькими компонентами одновременно.
Для того, чтобы компонент мог обрабатывать поступающие для него события, следует:
Любой метод блока прослушивания имеет один параметр - объект, производный от класса EventObject.
В классе EventObject определен метод Object getSource(), возвращающий объект, который инициировал событие. Некоторые классы, производные от EventObject, имеют свои методы, которые определяют объект, инициировавший событие. Например, класс ComponentEvent определяет метод getComponent, возвращающий объект Component.
Чтобы зарегистрировать блок прослушивания, нужно указать его в объявлении класса как наследуемый. В результате этого класс, наследующий данный интерфейс, должен содержать код реализации всех объявленных в интерфейсе методов. Если таких методов много, а нужен только один, то все равно приходится включать код реализации каждого объявленного в интерфейсе метода. Альтернативой такому подходу служит применение классов адаптеров.
Класс-адаптер для интерфейса блока прослушивания содержит "пустую" реализацию всех его методов. Таким образом, при создании класса, как производного от класса-адаптера, в качестве блока прослушивания можно указывать класс-адаптер и включать реализацию только необходимых методов.
На следующей схеме приведен пример обработки события "щелчок мышью" двумя способами: с применением интерфейса блока прослушивания и с применением адаптера блока прослушивания.
Применение интерфейса: | Применение класса адаптера: |
---|---|
public class MyClass implements MouseListener { ... myObject.addMouseListener(this); ... /* Реализация всех методов интерфейса MouseListener */ public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { ...// Код метода } } |
public class MyClass extends MouseAdapter { ... myObject.addMouseListener(this); ... /* Переопределение только одного метода адаптера MouseAdapter */ public void mouseClicked(MouseEvent e) } ...// Код переопределяемого метода } } |
Приведенный выше пример в практическом плане имеет один недостаток. При программировании классы приложений в большинстве случаев создаются как производные от классов Frame, Panel, JFrame, а классы апплетов - от класса Applet или JApplet. Но в языке Java реализовано только простое наследование, позволяющее иметь всего один наследуемый класс.
Поэтому, чтобы применять классы-адаптеры, можно использовать два способа реализации:
public class MyClass extends Applet { ... // Создание объекта класса адаптера: myObject.addMouseListener(new MyClassAdapter()); ... class MyClassAdapter extends MouseAdapter {//Объявление //внутреннего класса адаптера public void mouseClicked(MouseEvent e) { ... } // Реализация методов класса адаптера } }
public class MyClass extends Applet { ... // Создание объекта и реализация класса адаптера: myObject.addMouseListener(new MouseAdapter() { // Реализация переопределяемых методов класса адаптера public void mouseClicked(MouseEvent e) { } }); } }
Для того чтобы реализовать применение класса-адаптера с использованием вложенного класса, следует:
Для того чтобы реализовать применение класса адаптера с использованием вложенного анонимного класса-адаптера, следует:
Использование анонимных вложенных классов значительно улучшает читаемость кода.