Событие ActionEvent

We use cookies. Read the Privacy and Cookie Policy

Это простое событие означает, что надо выполнить какое-то действие. При этом неважно, что вызвало событие: щелчок мыши, нажатие клавиши или что-то другое.

В классе ActionEvent есть два полезных метода:

? getActionCommand ( ) возвращает в виде строки String надпись на кнопке JButton,

точнее, то, что установлено методом setActionCommand(String s) класса JButton, выбранный пункт меню или списка JList, или что-то другое, зависящее от компонента;

? getModifiers () — возвращает код клавиш <Alt>, <Ctrl>, <Meta> или <Shift>, если какая-нибудь одна или несколько из них были нажаты, в виде числа типа int. Узнать, какие именно клавиши были нажаты, можно сравнением со статическими константами этого класса alt_mask, ctrl_mask, meta_mask, shift_mask.

Примечание

Клавиши <Meta> на PC-клавиатуре нет, ее действие часто назначается на клавишу <Esc> или левую клавишу <Alt>.

Вот как, например, можно отследить нажатие клавиши <Alt> при щелчке по кнопке Open:

public void actionPerformed(ActionEvent ae){ if (ae.getActionCommand() == "Open" &&

(ae.getModifiers() | ActionEvent.ALT MASK) != 0){

// Какие-то действия

}

}

Обработка действий мыши

Событие MouseEvent возникает в компоненте по любой из семи причин:

? нажатие кнопки мыши — идентификатор mouse_pressed;

? отпускание кнопки мыши — идентификатор MOUSE_RELEASED;

? щелчок кнопкой мыши — идентификатор mouse_clicked (нажатие и отпускание не различаются);

? перемещение мыши — идентификатор mouse_moved;

? перемещение мыши с нажатой кнопкой — идентификатор mouse_dragged;

? появление курсора мыши в компоненте — идентификатор mouse_entered;

? выход курсора мыши из компонента — идентификатор mouse_exited.

Для их обработки есть семь методов в двух интерфейсах:

public interface MouseListener extends EventListener{ public void mouseClicked(MouseEvent e); public void mousePressed(MouseEvent e); public void mouseReleased(MouseEvent e); public void mouseEntered(MouseEvent e); public void mouseExited(MouseEvent e);

}

public interface MouseMotionListener extends EventListener{ public void mouseDragged(MouseEvent e); public void mouseMoved(MouseEvent e);

}

Эти методы могут получить от параметра e координаты курсора мыши в системе координат компонента методами e. getX (), e. getY ( ) или одним методом e . getPoint ( ), возвращающим экземпляр класса Point. Координаты курсора мыши относительно всего экрана, определяемые объектом класса GraphicsConfiguration, можно получить методами

e.getXOnScreen(), e.getYOnScreen() или e.getLocationOnScreen().

Двойной щелчок кнопкой мыши можно отследить методом e.getClickCount(), возвращающим количество щелчков. При перемещении мыши возвращается 0.

Узнать, какая кнопка была нажата, можно с помощью метода e.getModifiers() класса InputEvent сравнением со следующими статическими константами класса InputEvent:

? button1_mask — нажата первая кнопка, обычно левая;

? button2_mask — нажата вторая кнопка, обычно средняя, или одновременно нажаты обе кнопки на двухкнопочной мыши;

? button3_mask — нажата третья кнопка, обычно правая.

Приведем пример, уже ставший классическим. В листинге 15.4 представлен простейший вариант "рисовалки" — класс Scribble. При нажатии первой кнопки мыши методом mousePressed () запоминаются координаты курсора мыши. При протаскивании мыши вычерчиваются отрезки прямых между текущим и предыдущим положением курсора мыши методом mouseDragged(). На рис. 15.3 показан пример работы с этой программой.

Листинг 15.4. Простейшая программа рисования

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

public class ScribbleTest extends JFrame{

public ScribbleTest(String s){ super(s);

Scribble scr = new Scribble(this, 500, 500); JScrollPane pane = new JScrollPane(scr); pane.setSize(300, 300); add(pane, BorderLayout.CENTER);

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

p.add(b1); p.add(b2); p.add(b3); p.add(b4); p.add(b5);

JButton b1 = new JButton(,,Красный,,); b1.addActionListener(scr);

JButton b2 = new JButton(,,Зеленый,,); b2.addActionListener(scr);

JButton b3 = new JButtonC'^™^'); b3.addActionListener(scr);

JButton b4 = new JButton("Черный"); b4.addActionListener(scr);

JButton b5 = new JButton("Очистить") b5.addActionListener(scr);

setDefaultCloseOperation(EXIT ON CLOSE); pack();

setVisible(true);

}

public static void main(String[] args){ new ScribbleTest(" "Рисовалка"");

}}

class Scribble extends JPanel implements

ActionListener, MouseListener, MouseMotionListener{ protected int lastX, lastY, w, h; protected Color currColor = Color.black; protected JFrame f;

public Scribble(JFrame frame, int width, int height){ f = frame; w = width; h = height; enableEvents (AWTEvent.MOUSE_EVENT_MASK |

AWTEvent.MOUSE_MOTION_EVENT_MASK) ; addMouseListener(this); addMouseMotionListener(this);

}

public Dimension getPreferredSize(){ return new Dimension(w, h);

}

public void actionPerformed(ActionEvent event){

String s = event.getActionCommand();

if (s.equals(,,Очистить,,)) repaint();

else if (s.equals("Красный")) currColor = Color.red;

else if (s.equals("Зеленый")) currColor = Color.green;

else if (s.equals("Синий")) currColor = Color.blue;

else if (s.equals("Черный")) currColor = Color.black;

}

public void mousePressed(MouseEvent e){

if ((e.getModifiers() & MouseEvent.BUTTON1 MASK) == 0) return; lastX = e.getX(); lastY = e.getY();

}

public void mouseDragged(MouseEvent e){

if ((e.getModifiers() & MouseEvent.BUTTON1 MASK) == 0) return;

Graphics g = getGraphics(); g.setColor(currColor);

g.drawLine(lastX, lastY, e.getX(), e.getY());

lastX = e.getX(); lastY = e.getY();

}

public void mouseReleased(MouseEvent e){} public void mouseClicked(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseMoved(MouseEvent e){}

}

При создании класса-с^шателя Scribble и реализации интерфейсов MouseListener и MouseMotionListener пришлось реализовать все их семь методов, хотя мы отслежива-

ли только нажатие кнопки и перемещение мыши, и нам нужны были лишь методы mousePressed ( ) и mouseDragged( ). Для остальных методов мы задали пустые реализации.

Чтобы облегчить задачу реализации интерфейсов, имеющих более одного метода, созданы классы-адаптеры.

Рис. 15.3. Пример работы с программой рисования

Упражнение

2. Реализуйте оставшиеся методы интерфейсов-слушателей событий мыши.

Классы-адаптеры

Классы-адаптеры представляют собой пустую реализацию интерфейсов-слушателей,

имеющих более одного метода. Их имена составляются из имени события и слова

"Adapter". Например, для действий с мышью есть два класса-адаптера. Выглядят они

очень просто:

public abstract class MouseAdapter implements MouseListener{ public void mouseClicked(MouseEvent e){} public void mousePressed(MouseEvent e){} public void mouseReleased(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void mouseExited(MouseEvent e){} public void mouseMoved(MouseEvent e){} public void mouseDragged(MouseEvent e){} public void mouseWheelMoved(MouseEvent e){}

}

public abstract class MouseMotionAdapter implements MouseMotionListener{ public void mouseDragged(MouseEvent e){} public void mouseMoved(MouseEvent e){}

}

Вместо того чтобы реализовать интерфейс, можно расширять эти классы. Не бог весть что, но полезно для создания безымянного вложенного класса, как у нас и делалось для закрытия окна. Там мы использовали класс-адаптер WindowAdapter.

Классов-адаптеров всего семь. Кроме уже упомянутых трех классов, это классы

ComponentAdapter, ContainerAdapter, FocusAdapter и KeyAdapter.

Управление колесиком мыши

Колесико, дополняющее среднюю кнопку мыши, очень удобно и популярно. Его использование встроено в Java SE, начиная с версии JDK 1.4, и применяется, например, в контейнере JScrollPane. Если же разработчику нужно создать свой компонент, в котором прокрутка осуществляется колесиком мыши, то он может задать обработку события MouseWheelEvent.

Класс MouseWheelEvent расширяет класс MouseEvent, следовательно, содержит все его поля и методы. Дополнительно он различает два типа прокрутки: прокрутку блока, отмечаемую статическим полем wheel_block_scroll, и прокрутку одной единицы — статическое поле wheel_unit_scroll. Тип прокрутки, а также смысл понятий "блок" и "единица" определяется графической оболочкой операционной системы и возвращается методом getScrollType (). Например, блок — это страница текста, а единица — одна строка.

Если тип прокрутки WHEEL_UNIT_SCROLL, то метод getUnitsToScroll() возвращает количество прокрученных единиц с учетом направления вращения колесика: на себя — положительное число, от себя — отрицательное. Метод getScrollAmount () возвращает то же число без знака. Конкретное значение зависит от платформы.

Если же разработчик не хочет использовать понятие "единица", то он может методом getWheelRotation () отследить количество "щелчков", сделанных колесиком во время прокрутки. При этом положительное число возвращается при повороте колесика на себя и означает прокрутку вниз, а отрицательное — при повороте колесика от себя, прокрутка вверх.

Интерфейс MouseWheelListener описывает один метод

public void mouseWheelMoved(MouseWheelEvent e);

которому передается объект-событие, происшедшее в результате вращения колесика мыши. В листинге 15.5 приведен тренировочный пример работы с колесиком мыши.

Листинг 15.5. Событие колесика мыши

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

public class WheelEv extends JFrame

implements MouseWheelListener{

JTextArea ta = new JTextArea(5, 30);

WheelEv(){

super(" Колесико мыши"); getContentPane().add(ta);

ta.addMouseWheelListener(this); setSize(400, 400);

setDefaultCloseOperation(EXIT ON CLOSE); setVisible(true);

}

public void mouseWheelMoved(MouseWheelEvent e){

if (e.getScrollType() == MouseWheelEvent.WHEEL UNIT SCROLL) ta.append(" Единицы = " + e.getUnitsToScroll() +

" Количество = "+ e.getScrollAmount() +

" Вращение = " + e.getWheelRotation() + " ");

}

public static void main(String[] args){ new WheelEv();

}

}

Рисунок 15.4 показывает конкретные значения, полученные этой программой в операционной системе Windows XP.

Рис. 15.4. Значения, полученные от колесика мыши

Обработка действий клавиатуры

Событие KeyEvent происходит в компоненте по любой из трех причин:

? нажата клавиша — идентификатор key_pressed;

? отпущена клавиша — идентификатор key_released;

? введен символ — идентификатор key_typed.

Последнее событие возникает из-за того, что некоторые символы вводятся нажатием нескольких клавиш, например заглавные буквы вводятся комбинацией клавиш ^Ый>+<буква>. Вспомните еще <АИ>-ввод в MS Windows. Нажатие функциональных клавиш, например <F1>, не вызывает событие key_typed.

Обрабатываются эти события тремя методами, описанными в интерфейсе:

public interface KeyListener extends EventListener{ public void keyTyped(KeyEvent e);

public void keyPressed(KeyEvent e); public void keyReleased(KeyEvent e);

}

Аргумент e этих методов может дать следующие сведения.

Метод e.getKeyChar() возвращает символ Unicode типа char, связанный с клавишей. Если с клавишей не связан никакой символ, то возвращается константа char_undefined.

Метод e.getKeyCode () возвращает код клавиши в виде целого числа типа int. В классе KeyEvent определены коды всех клавиш в виде констант, называемых виртуальными кодами клавиш (virtual key codes), например: vk_f1, vk_shift, vk_a, vk_b, vk_plus. Они перечислены в документации к классу KeyEvent. Фактическое значение виртуального кода зависит от языка и раскладки клавиатуры. Чтобы узнать, какая клавиша была нажата, надо сравнить результат выполнения метода getKeyCode () с этими константами. Если кода клавиши нет, как происходит при наступлении события key_typed, то возвращается значение vk_undefined.

Чтобы узнать, не нажата ли одна или несколько клавиш-модификаторов <Alt>, <Ctrl>, <Meta>, <Shift>, надо воспользоваться унаследованным от класса InputEvent методом getModifiers () и сравнить его результат с константами ALT_MASK, ctrl_mask, meta_mask,

SHIFT_MASK. Другой способ применить логические методы isAltDown(), isControlDown ( ),

isMetaDown(), isShiftDown().

Добавим в листинг 15.3 возможность очистки поля ввода tf после нажатия клавиши <Esc>. Для этого перепишем вложенный класс-слушатель TextMove:

class TextMove implements ActionListener, KeyListener{ public void actionPerformed(ActionEvent ae){ ta.append(tf.getText()+" ");

}

public void keyPressed(KeyEvent ke){

if (ke.getKeyCode() == KeyEvent.VK ESCAPE) tf.setText("");

}

public void keyReleased(KeyEvent ke){} public void keyTyped(KeyEvent ke){}

}

Упражнение

3. Реализуйте обработку нажатия различных клавиш.

Событие TextEvent

Событие TextEvent происходит только по одной причине — изменению текста — и отмечается идентификатором text_value_changed.

Соответствующий интерфейс имеет только один метод:

public interface TextListener extends EventListener{ public void textValueChanged(TextEvent e);

От аргумента e этого метода можно получить ссылку на объект-источник события методом getSource (), унаследованным от класса EventObj ect, например, так:

JTextComponent tc = (JTextComponent)e.getSource();

String s = tc.getText();

// Дальнейшая обработка

Событие изменения ChangeEvent

Еще одно событие общего характера ChangeEvent происходит при изменении состояния компонента Swing: щелчке кнопкой мыши на кнопке Swing любого типа, выборе пункта меню, движении ползунка и "градусника", смене страниц на панели с вкладками. Большинство этих компонентов реагируют на собственные события, более удобные для обработки, но для окна выбора цвета JColorChooser и ползунка JSlider это основное событие.

Поскольку событие класса aangeEvent носит такой общий характер, в этом классе нет собственных методов, только унаследованный метод getSource ( ).

Слушатель этого события changeListener обладает всего одним методом:

public void stateChanged(ChangeEvent);

При обработке события следует получить ссылку на источник и извлечь из него всю необходимую информацию, например:

import javax.swing.event.*;

class SliderHandler implements ChangeListener{

private int threshold; private JLabel l;

public SliderHandler(int threshold, JLabel l){ this.threshold = threshold; this.l = l;

}

public void stateChanged(ChangeEvent e){

JSlider sl = (JSlider)e.getSource(); if (!sl.getValueIsAdjusting())

if (threshold <= (int)sl.getValue()) l.setText("Порог достигнут");

}

}

Обработка действий с окном

Событие WindowEvent может произойти по двенадцати причинам:

? окно открылось — идентификатор window_opened;

? окно закрылось — идентификатор window_closed;

? попытка закрытия окна — идентификатор window_closing;

? окно получило фокус — идентификатор window_activated;

? процесс получения фокуса — идентификатор window_gained_focus;

? окно потеряло фокус — идентификатор window_deactivated;

? процесс потери фокуса — идентификатор window_lost_focus;

? окно свернулось в ярлык — идентификатор window_iconified;

? окно развернулось — идентификатор window_deiconified;

? всякое изменение состояния окна — window_state_changed;

? окно стало первым — window_first;

? окно стало последним — window_last.

Соответствующий интерфейс содержит семь методов:

public interface WindowListener extends EventListener { public void windowOpened(WindowEvent e); public void windowClosing(WindowEvent e); public void windowClosed(WindowEvent e); public void windowIconified(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowActivated(WindowEvent e); public void windowDeactivated(WindowEvent e);

}

Аргумент e этих методов дает ссылку типа Window на окно-источник методом

e.getWindow().

Чаще всего эти события используются для перерисовки окна методом repaint () при изменении его размеров и для остановки приложения при закрытии окна.