Обработка любого события (нажатие кнопки, щелчок мышью и др.) состоит в связывании события с методом, его обрабатывающим. Принцип обработки событий, начиная с Java 2, базируется на модели делегирования событий. В этой модели имеется блок прослушивания события (EventListener), который ждет поступления события определенного типа от источника, после чего обрабатывает его и возвращает управление. Источник – это объект, который генерирует событие, если изменяется его внутреннее состояние, например, изменился размер, изменилось значение поля, произведен щелчок мыши по форме или выбор значения из списка. После генерации объект-событие пересылается для обработки зарегистрированному в источнике блоку прослушивания как параметр его методов – обработчиков событий.
Блоки прослушивания Listener представляют собой объекты классов, реализующих интерфейсы прослушивания событий, определенных в пакете java.awt.event. Соответствующие методы, объявленные в используемых интерфейсах, необходимо явно реализовать при создании собственных классов прослушивания. Эти методы и являются обработчиками события. Передаваемый источником блоку прослушивания объект-событие является аргументом обработчика события. Объект класса – блока прослушивания события необходимо зарегистрировать в источнике методом
источник.addСобытиеListener(объект_прослушиватель);
После этого объект-прослушиватель (Listener) будет реагировать именно на данное событие и вызывать метод «обработчик события». Такая логика обработки событий позволяет легко отделить интерфейсную часть приложения от функциональной, что считается необходимым при проектировании современных приложений. Удалить слушателя определенного события можно с помощью методаremoveСобытиеListener().
Источником событий могут являться элементы управления: кнопки (JButton,JCheckbox, JRadioButton), списки, кнопки-меню. События могут генерироваться фреймами и апплетами, как mouse- и key-события. События генерируются окнами при развертке, сворачивании, выходе из окна. Каждый класс-источник определяет один или несколько методов addСобытиеListener() или наследует эти методы
Когда событие происходит, все зарегистрированные блоки прослушивания уведомляются и принимают копию объекта события. Таким образом источник вызывает метод-обработчик события, определенный в классе, являющемся блоком прослушивания, и передает методу объект события в качестве параметра. В качестве блоков прослушивания на практике используются внутренние классы. В этом случае в методе, регистрирующем блок прослушивания в качестве параметра, используется объект этого внутреннего класса.
Каждый интерфейс, включаемый в блок прослушивания, наследуется от интерфейсаEventListener и предназначен для обработки определенного типа событий. При этом он содержит один или несколько методов, которые всегда принимают объект события в качестве единственного параметра и вызываются в определенных ситуациях. В таблице приведены некоторые интерфейсы и их методы, которые должны быть реализованы в классе прослушивания событий, реализующем соответствующий интерфейс:
| Интерфейсы | Обработчики события |
| ActionListener | actionPerformed(ActionEvent e) |
| AdjustmentListener | adjustmentValueChanged(AdjustmentEvent e) |
| ComponentListener | componentResized(ComponentEvent e)
componentMoved(ComponentEvent e) componentShown(ComponentEvent e) componentHidden(ComponentEvent e) |
| ContainerListener | componentAdded(ContainerEvent e)componentRemoved(
ContainerEvent e) |
| FocusListener | focusGained(FocusEvent e)focusLost(FocusEvent e) |
| ItemListener | itemStateChanged(ItemEvent e) |
| KeyListener | keyPressed(KeyEvent e)keyReleased(KeyEvent e)
keyTyped(KeyEvent e) |
| MouseListener | mouseClicked(MouseEvent e)mousePressed(MouseEvent e)
mouseReleased(MouseEvent e) mouseEntered(MouseEvent e) mouseExited(MouseEvent e) |
| MouseMotionListener | mouseDragged(MouseEvent e)mouseMoved(MouseEvent e) |
| TextListener | textValueChanged(TextEvent e) |
| WindowListener | windowOpened(WindowEvent e)windowClosing(WindowEvent e)
windowClosed(WindowEvent e) windowIconified(WindowEvent e) windowDeiconified(WindowEvent e) windowActivated(WindowEvent e) |
Событие, которое генерируется в случае возникновения определенной ситуации и затем передается зарегистрированному блоку прослушивания для обработки, – это объект класса событий. В корне иерархии классов событий находится суперклассEventObject из пакета java.util. Этот класс содержит два метода: getSource(), возвращающий источник событий, и toString(), возвращающий строчный эквивалент события. Абстрактный класс AWTEvent из пакета java.awt является суперклассом всех AWT-событий, связанных с компонентами. Метод getID() определяет тип события, возникающего вследствие действий пользователя в визуальном приложении. Ниже приведены некоторые из классов событий, производных от AWTEvent, и расположенные в пакете java.awt.event:
ActionEvent – генерируется: при нажатии кнопки; двойном щелчке клавишей мыши по элементам списка; при выборе пункта меню;
AdjustmentEvent – генерируется при изменении полосы прокрутки;
ComponentEvent – генерируется, если компонент скрыт, перемещен, изменен в размере или становится видимым;
FocusEvent – генерируется, если компонент получает или теряет фокус ввода;
TextEvent – генерируется при изменении текстового поля;
ItemEvent – генерируется при выборе элемента из списка.
Класс InputEvent является абстрактным суперклассом событий ввода (для клавиатуры или мыши). События ввода с клавиатуры обрабатывает класс KeyEvent, события мыши – MouseEvent.
Чтобы реализовать методы-обработчики событий, связанных с клавиатурой, необходимо определить три метода, объявленные в интерфейсе KeyListener. При нажатии клавиши генерируется событие со значением KEY_PRESSED. Это приводит к запросу обработчика событий keyPressed(). Когда клавиша отпускается, генерируется событие со значением KEY_RELEASED и выполняется обработчик keyReleased(). Если нажатием клавиши сгенерирован символ, то посылается уведомление о событии со значением KEY_TYPED и вызывается обработчик keyTyped().
Для регистрации события приложение-источник из своего объекта должно вызвать метод addКеуListener(KeyListener el), регистрирующий блок прослушивания этого события. Здесь el – ссылка на блок прослушивания события.
/* пример # 1 : обработка событий клавиатуры: MyKey.java */
package chapt12;
import java.awt.*;
import java.awt.event.*;
import javax.swing.JApplet;
public class MyKey extends JApplet {
private String msg = " ";
private int x = 0, y = 20; // координаты вывода
private class AppletKeyListener
implements KeyListener {
// реализация всех трех методов интерфейса KeyListener
public void keyPressed(KeyEvent e) {
showStatus("Key Down");
} // отображение в строке состояния
public void keyReleased(KeyEvent e) {
showStatus("Key Up");
} // отображение в строке состояния
public void keyTyped(KeyEvent e) {
msg += e.getKeyChar();
repaint(); // перерисовать
}
}
public void init() {
/* регистрация блока прослушивания */
addKeyListener(new AppletKeyListener());
requestFocus(); // запрос фокуса ввода
}
public void paint(Graphics g) {
// значение клавиши в позиции вывода
g.drawString(msg, x, y);
}
}
Рис. 12.1. Результат нажатия клавиши отображен в строке состояния
Коды специальных клавиш (перемещение курсора, функциональных клавиш) недоступны через keyTyped(), для обработки нажатия этих клавиш используется методkeyPressed().
В качестве блока прослушивания в методе init() зарегистрирован внутренний классAppletKeyListener. Затем в блоке прослушивания реализованы все три метода обработки события, объявленные в интерфейсе KeyListener.
В следующем апплете проверяется принадлежность прямоугольнику координат нажатия клавиши мыши с помощью реализации интерфейса MouseListener и событияMouseEvent.
/* пример # 2 : события нажатия клавиши мыши: MyRect.java */
package chapt12;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyRect extends JApplet {
private Rectangle rect =
new Rectangle(20, 20, 100, 60);
private class AppletMouseListener//блок обработки событий
implements MouseListener {
/* реализация всех пяти методов интерфейса MouseListener */
public void mouseClicked(MouseEvent me) {
int x = me.getX();
int y = me.getY();
if (rect.contains(x, y)) {
showStatus(
"клик в синем прямоугольнике");
} else {
showStatus("клик в белом фоне");
}
}
// реализация остальных методов интрефейса пустая
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
public void init() {
setBackground(Color.WHITE);
/* регистрация блока прослушивания */
addMouseListener(new AppletMouseListener());
}
public void paint(Graphics g) {
g.setColor(Color.BLUE);
g.fillRect(rect.x, rect.y,
rect.width, rect.height);
}
}
Рис. 12.2. Результат нажатия кнопки отображен в строке состояния
Способ обработки событий в компонентах Swing – это интерфейс (графические компоненты) и реализация (код обработчика события, который запускается при возникновении события). Каждое событие содержит сообщение, которое может быть обработано в разделе реализации.
При использовании компонента JButton определяется событие, связанное с нажатием кнопки. Для регистрации заинтересованности блока прослушивания в этом событии вызывается метод addActionListener() объектом класса JButton. ИнтерфейсActionListener содержит единственный метод actionPerformed(), который нужно реализовать в блоке обработки в соответствии с поставленной задачей: извлечь числа из двух текстовых полей, сложить их и поместить результат в метку.
/* пример # 3 : регистрация, генерация и обработка ActionEvent:
SimpleButtonAction.java */
package chapt12;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleButtonAction extends JApplet {
private JButton additionBtn = new JButton("Сложить");
private JTextField txtField1 = new JTextField(3);
private JTextField txtField2 = new JTextField(3);
private JLabel answer = new JLabel();
private class ButtonListener
implements ActionListener {
// реализация класса- обработчика события
public void actionPerformed(ActionEvent ev) {
try {
int t1, t2;
t1 = Integer.parseInt(txtField1.getText());
t2 = Integer.parseInt(txtField2.getText());
answer.setText("Ответ: " + (t1 + t2));
showStatus("Выполнено успешно!");
} catch (NumberFormatException e) {
showStatus("Ошибка ввода!");
}
/*
* String s1, s2; извлечение надписи на кнопке из события
* s1 = ((JButton)ev.getSource()).getText();
*/
// извлечение команды из события
// s2 = ev.getActionCommand();
/*
* извлечение из события объекта, ассоциированного с кнопкой
* if (ev.getSource() == additionBtn)
* применяется если обрабатываются
* события нескольких кнопок одним обработчиком
*/
}
}
public void init() {
Container c = getContentPane();
setLayout(new FlowLayout());/* «плавающее»
размещение компонентов*/
c.add(txtField1);
c.add(txtField2);
// регистрация блока прослушивания события
additionBtn.addActionListener(
new ButtonListener());
c.add(additionBtn);
c.add(answer);
}
}
Рис. 12.3. Обработка события кнопки
При создании кнопки вызывается конструктор JButton со строкой, которую нужно поместить на кнопке. JButton – это компонент, который автоматически заботится о своей перерисовке. Размещение кнопки на форме обычно производится внутри методаinit() вызовом метода add() класса Container.