Обратное действие — отказ от обработчика, прекращение прослушивания — выполняется методом removeXxxListener ().

Таким образом, компонент-источник, в котором произошло событие, не занимается его обработкой. Он обращается к экземпляру класса-слушателя, умеющего обрабатывать события, делегирует (delegate) ему полномочия по обработке.

Такая схема получила название схемы делегирования (delegation). Она удобна тем, что мы можем легко сменить класс-обработчик и обработать событие по-другому или назначить несколько обработчиков одного и того же события. С другой стороны, мы можем один обработчик назначить на прослушивание нескольких объектов-источников событий.

Эта схема кажется слишком сложной, но мы ею часто пользуемся в жизни. Допустим, мы решили оборудовать квартиру. Мы помещаем в нее, как в контейнер, разные компоненты: мебель, сантехнику, электронику, антиквариат. Мы предполагаем, что может произойти неприятное событие — квартиру посетят воры, — и хотим его обработать. Мы знаем, что существуют классы-обработчики этого события — охранные агентства, — и обращаемся к некоторому экземпляру такого класса. Компоненты-источники события, т. е. те, которые могут быть украдены, присоединяют к себе датчики методом вида addXxxListener (). Затем экземпляр-обработчик "слушает", что происходит в объектах, к которым он подключен. Он реагирует на наступление только одного события — похищения прослушиваемого объекта, — прочие события, например короткое замыкание или прорыв водопроводной трубы, его не интересуют. При наступлении "своего" события он действует по контракту, записанному в методе обработки события.

Приведем пример. Пусть в контейнер типа JFrame помещено поле ввода tf типа JTextField, нередактируемая область ввода ta типа JTextArea и кнопка b типа JButton. В поле tf вводится строка, после нажатия клавиши или щелчка кнопкой мыши по кнопке b строка переносится в область ta. После этого можно снова вводить строку в поле tf и т. д.

Здесь и при нажатии клавиши , и при щелчке кнопкой мыши возникает событие класса ActionEvent, причем оно может произойти в двух компонентах-источниках: поле tf или кнопке b. Обработка события в обоих случаях заключается в получении строки текста из поля tf (например, методом tf.getText ()) и помещения ее в область ta (скажем, методом ta.append()). Значит, можно написать один обработчик события ActionEvent, реализовав соответствующий интерфейс, который называется ActionListener. В этом интерфейсе есть всего один метод actionPerformed (), который надо определить.

Итак, пишем:

class TextMove implements ActionListener{ private JTextField tf; private JTextArea ta;

TextMove(JTextField tf, JTextArea ta){ this.tf = tf; this.ta = ta;

}

public void actionPerformed(ActionEvent ae){ ta.append(tf.getText()+"\n");

}

}

Обработчик событий готов. При наступлении события типа ActionEvent будет создан экземпляр класса-обработчика TextMove, конструктор получит ссылки на конкретные поля объекта-источника, метод actionPerformed (), автоматически включившись в работу, перенесет текст из одного поля в другое.

Теперь напишем класс-контейнер, в котором находятся источники tf и b события ActionEvent, и подключим к ним слушателя этого события TextMove, передав им ссылки на него методом addActionListener ( ), как показано в листинге 15.1.

Листинг 15.1. Обработка события ActionEvent

import java.awt.*; import java.awt.event.*; import javax.swing.*;

class MyNotebook extends JFrame{

MyNotebook(String title){ super(title);

JTextField tf = new JTextField("Вводите текст", 50); add(tf, BorderLayout.NORTH);

JTextArea ta = new JTextArea(); ta.setEditable(false); add(ta);

JPanel p = new JPanel(); add(p, BorderLayout.SOUTH);

JButton b = new JButton("Перенести"); p.add(b);

tf.addActionListener(new TextMove(tf, ta)); b.addActionListener(new TextMove(tf, ta));

setSize(300, 200); setVisible(true);

}

public static void main(String[] args){

JFrame f = new MyNotebook(" Обработка ActionEvent"); f.setDefaultCloseOperation(EXIT ON CLOSE);

}

}

// Текст класса TextMove // ...

На рис. 15.2 показан результат работы с этой программой.

В листинге 15.1 в методах addActionListener() создаются два экземпляра класса TextMove — для прослушивания поля tf и для прослушивания кнопки b. Можно создать один экземпляр класса TextMove, он будет прослушивать оба компонента:

Перейти на страницу:

Все книги серии В подлиннике

Похожие книги