Московский государственный университет имени М.В.Ломоносова
Опубликован: 01.11.2004 | Доступ: свободный | Студентов: 11271 / 455 | Оценка: 4.12 / 4.01 | Длительность: 19:20:00
ISBN: 978-5-9556-0077-9
Специальности: Программист
Лекция 26:

Библиотека классов JDK. Основы построения интерфейса пользователя на языке Java. События

< Лекция 25 || Лекция 26: 1234 || Лекция 27 >
Аннотация: В лекции приводятся основные принципы построения интерфейса пользователя на языке Java, описывается модель управления событиями, вводится понятие блоков прослушивания и классов адаптеров, рассматриваются методы обработчики событий.
Ключевые слова: Swing, AWT, dnd, bean, источник события

События

Типы событий

Событием в языке Java является объект. Все события можно разделить на две группы: события низкого уровня и семантические события.

К событиям низкого уровня относятся:

  • события от клавиатуры и мыши;
  • события от окна Windows;
  • события от компонента;
  • события от контейнера;
  • события от перемещения фокуса ввода.

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

Блоки прослушивания

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

Объект регистрирует блок прослушивания событий. Блок прослушивания - это интерфейс, который определяет набор методов-обработчиков событий, объявленных как ожидаемые события.

Регистрация блока прослушивания для компонента состоит в вызове метода, начинающегося с префикса add, за которым идет имя блока прослушивания. Имена блоков прослушивания оканчиваются суффиксом Listener.

Для одного компонента можно зарегистрировать только один блок прослушивания. Но один блок прослушивания может использоваться несколькими компонентами одновременно.

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

  1. при объявлении класса указать наследуемые этим классом интерфейсы, содержащие методы-обработчики событий;
  2. добавить блоки прослушивания для компонентов;
  3. все методы-обработчики, объявленные в наследуемом интерфейсе, реализовать в классе компонента.

Любой метод блока прослушивания имеет один параметр - объект, производный от класса 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) {
                 }
     	});
         }
     }

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

  1. добавить блок прослушивания компонента и указать в качестве параметра код new имя_внутреннего_класса (например, addMouseListener(new MouseAdapter() );
  2. добавить код с объявлением внутреннего класса, включающий реализацию требуемых методов обработчиков событий (например, class MyClassAdapter extends MouseAdapter { public void mouseClicked(MouseEvent e) { ѕ }}.)

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

  1. добавить блок прослушивания компонента и указать в качестве параметра код new имя_класса_адаптера { } (например, addMouseListener(new MyClassAdapter(){ } );
  2. вставить в фигурные скобки после имени класса адаптера код переопределяемых методов (например, { public void mouseClicked(MouseEvent e) { ѕ }} ).

Использование анонимных вложенных классов значительно улучшает читаемость кода.

< Лекция 25 || Лекция 26: 1234 || Лекция 27 >
Александр Демьяненко
Александр Демьяненко

Можно ли сдавать один и тот же тест несколько раз?
Или же один и тот же тест можно сдать лишь однажды?

Максим Стогний
Максим Стогний

Добрый день!

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

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

при этом можно было  тип_функции во втором описании заменить на тип_метода? Т.е.:

тип_метода (*имя_ метода_указателя)
    (список параметров);