Есть два способа обработки нажатия клавиш:- Установка Key Listener'a на компонент
- Создание элемента на основе Action класса
Для иллюстрации примеров, создадим окно (JFrame), на него положим панель (JPanel) с кнопками (JButton). Описание основного класса, создание окна и панели - пропустим, если вы начали разбираться с обработкой нажатия клавиш, вы это уже прошли и знаете. Наш пример будет содержать три кнопки с название цвета и менять фон окна при нажатии на них.
Способ 1 Этот метод подходит для новичков, тех кто только начал изучать JAVA. После знакомства со вторым методом, больше не чего хорошего не напишу о нем.
Разберем по порядку что к чему. Обработка нажатия клавиши происходит только для компонента который находится в фокусе (выделен). В фокусе может быть только один элемент, из этого следует что для того чтобы в вашем приложении срабатывали "горячие" клавиши обработчик надо вешать на все элементы у которых может быть фокус.
Для обработки нажатия клавиш на элементе, требуется использовать класс с интерфейсом KeyListener или наследовать от класса KeyAdapter.
В случаем использования интерфейса, нам требуется реализовать три метода:- void keyTyped(KeyEvent e)
- void keyPressed(KeyEvent e)
- void keyTyped(KeyEvent e)
В случае наследования от класса KeyAdapter, реализуем только тот метод который надо. В примере я пошел по второму варианту, так как использовал только метод keyPressed
Дабы иметь свободный доступ к полям класса PanelButtonSimple, класс, отвечающий за обработку нажатия, сделал внутренним. Далее все просто: получаем код клавиши (e.getKeyCode()) сравниваем его с требуемым нам (KeyEvent.VK_Y) и проверяем нажат ли Ctrl (e.isControlDown()). Если все сходится выполняем действие.
Регистрируем наш класс для всех кнопок и проверяем работу.
Основной класс
| Java | 1
2
3
4
5
6
7
| public class TestAction {
public static void main (String[] arg){
Window frame = new Window();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
} |
|
JFrame
| Java | 1
2
3
4
5
6
7
8
9
| class Window extends JFrame{
Window(){
super("Test Action");
setSize(200,200);
setLocationRelativeTo(null);
PanelButtonSimple pbs = new PanelButtonSimple();
add(pbs);
}
} |
|
JPanel с кнопками
| Java | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| /**
* Панель реализует просту установку "горячих" клавиш для нажатия на кнопки
*/
class PanelButtonSimple extends JPanel{
JButton blue;
JButton yellow;
JButton green;
PanelButtonSimple(){
blue = new JButton("Blue");
blue.addKeyListener(new KeyActionSimle());//наш обработчик
blue.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setBackground(Color.BLUE);
}
});
yellow = new JButton("Yellow");
yellow.addKeyListener(new KeyActionSimle());//наш обработчик
yellow.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setBackground(Color.YELLOW);
}
});
green = new JButton("Green");
green.addKeyListener(new KeyActionSimle());//наш обработчик
green.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setBackground(Color.GREEN);
}
});
add(blue);
add(yellow);
add(green);
}
/**
* Внутренний класс который обрабатывает нажатие клавиш
*/
class KeyActionSimle extends KeyAdapter{
@Override
public void keyPressed(KeyEvent e) {
//обработчик нажатия на кнопки (ctrl+Y/ctrl+G/ctrl+B)
if (e.getKeyCode() == KeyEvent.VK_Y && e.isControlDown()) {
yellow.doClick();//нажатие клавиши
//или setBackground(Color.YELLOW);
}
else if (e.getKeyCode() == KeyEvent.VK_G && e.isControlDown()) {
green.doClick();
}
else if (e.getKeyCode() == KeyEvent.VK_B && e.isControlDown()) {
blue.doClick();
}
}
}
} |
|
Способ 2 Второй метод использует наследника класс AbstractAction. Кто хочет почитать о нем, идут за официальной документацией. Много о нем не расскажу, сам только начал знакомится с ним. Покажу только как с ним работать в нашем примере.
Наш класс ActionButton (наследник AbstractAction) делает две вещи задает название для кнопки и действие при нажатии. При наследовании от AbstractAction, обязательно требуется переопределить метод public void actionPerformed(ActionEvent e).
Когда создается кнопка на основе класса Action, данные для кнопки (иконка, название, всплывающая подсказка, действие...) берутся и класса Action. По этому при реализации своего класса Action учитывайте эту особенность.
В нашем случае нам понадобится - название кнопки и цвет на который будет меняться фон.
Конструктор нашего Action класса:
| Java | 1
2
3
4
| ActionButton(String name, Color c){
putValue(Action.NAME, name);//аргумент name используем для имени кнопки
putValue("color", c);// аргумент с используем для установки цвета
} |
|
Обработчик нажатия на кнопку
| Java | 1
2
3
| public void actionPerformed(ActionEvent e) {
setBackground((Color)getValue("color"));
} |
|
Создание кнопки на основе Action
| Java | 1
2
| ActionButton blueAction = new ActionButton("Blue", Color.BLUE);
new JButton(blueAction) |
|
Подготовка на этом завершена.
Теперь требуется все это связать в одну композицию.
1. Создаем экземпляр класса InputMap на основе нашей панели (на которой кнопки)
| Java | 1
| InputMap imap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); |
|
Аргумент WHEN_ANCESTOR_OF_FOCUSED_COMPONENT - указывает что обрабатываться будут все элементы на панели.
2. Добавить в созданный InputMap комбинации клавиш при которых будет срабатывать то или иное действие, и привязать к комбинации метку
| Java | 1
| imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue"); |
|
KeyStroke.getKeyStroke - поддерживает несколько вариантов вызова: просто в текстовом виде или значение кнопки. Можно было написать так: | Java | 1
| imap.put(KeyStroke.getKeyStroke(KeyEvent.VK_B,KeyEvent.CTRL_DOWN_MASK), "panel.blue"); |
|
3. Создать ActionMap на основе нашей панели | Java | 1
| ActionMap amap = getActionMap(); |
|
4. Связать полученные InputMap и ActionMap, для этого в ActionMap добавляются метки из InputMap и привязываются к ним созданные экземпляры класса Action
imap.put(KeyStroke.getKeyStroke(KeyEvent .VK_B,KeyEvent.CTRL_DOWN_MASK), "panel.blue");
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
imap.put(KeyStroke.getKeyStroke("ctrl G"), "panel.green");
amap.put("panel.blue", blueAction);
amap.put("panel.yellow", yellowAction);
amap.put("panel.green", greenAction);
| Все. На этом установка и настройка "горячих" клавиш закончена. С непривычки второй метод показался не понятным и сложным, но пока все это писал разобрался, не чего сложного или не понятного тут нет.
JFrame
| Java | 1
2
3
4
5
6
7
8
9
| class Window extends JFrame{
Window(){
super("Test Action");
setSize(200,200);
setLocationRelativeTo(null);
PanelButton pb = new PanelButton();
add(pb);
}
} |
|
JPanel с кнопками
| Java | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| class PanelButton extends JPanel{
PanelButton(){
ActionButton blueAction = new ActionButton("Blue", Color.BLUE);
ActionButton yellowAction = new ActionButton("Yellow", Color.YELLOW);
ActionButton greenAction = new ActionButton("Green", Color.GREEN);
add(new JButton(blueAction));
add(new JButton(yellowAction));
add(new JButton(greenAction));
InputMap imap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
imap.put(KeyStroke.getKeyStroke("ctrl B"), "panel.blue");
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
imap.put(KeyStroke.getKeyStroke("ctrl G"), "panel.green");
ActionMap amap = getActionMap();
amap.put("panel.blue", blueAction);
amap.put("panel.yellow", yellowAction);
amap.put("panel.green", greenAction);
}
class ActionButton extends AbstractAction{
ActionButton(String name, Color c){
putValue(Action.NAME, name);
putValue("color", c);
}
@Override
public void actionPerformed(ActionEvent e) {
setBackground((Color)getValue("color"));
}
}
} |
|
п.с. Все это писалось в больше степени для себя, дабы как то закрепить и упорядочить прочитанное. Все это хорошо описано у Хорстманна.
|