Обратное действие — отказ от обработчика, прекращение прослушивания — выполняется методом removeXxxListener ().
Таким образом, компонент-источник, в котором произошло событие, не занимается его обработкой. Он обращается к экземпляру класса-слушателя, умеющего обрабатывать события,
Такая схема получила название схемы
Эта схема кажется слишком сложной, но мы ею часто пользуемся в жизни. Допустим, мы решили оборудовать квартиру. Мы помещаем в нее, как в контейнер, разные компоненты: мебель, сантехнику, электронику, антиквариат. Мы предполагаем, что может произойти неприятное событие — квартиру посетят воры, — и хотим его обработать. Мы знаем, что существуют классы-обработчики этого события — охранные агентства, — и обращаемся к некоторому экземпляру такого класса. Компоненты-источники события, т. е. те, которые могут быть украдены, присоединяют к себе датчики методом вида addXxxListener (). Затем экземпляр-обработчик "слушает", что происходит в объектах, к которым он подключен. Он реагирует на наступление только одного события — похищения прослушиваемого объекта, — прочие события, например короткое замыкание или прорыв водопроводной трубы, его не интересуют. При наступлении "своего" события он действует по контракту, записанному в методе обработки события.
Приведем пример. Пусть в контейнер типа JFrame помещено поле ввода tf типа JTextField, нередактируемая область ввода ta типа JTextArea и кнопка b типа JButton. В поле tf вводится строка, после нажатия клавиши
Здесь и при нажатии клавиши
Итак, пишем:
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.
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, он будет прослушивать оба компонента: