Назад
Вперед
4.1. Просмотр кодов клавиш в приложении JDK 1.1
На примере автономного приложения Java мы
покажем вам способ обработки событий от
клавиатуры. В своем окне наше приложение
показывает код и название каждой нажатой или
отжатой клавиши. При этом мы используем механизм
обработки событий, принятый в JDK версии 1.1 и более
старших версий.
Исходный текст примера
Архив проекта для Java WorkShop 2.0
Немного теории
Реализовав интерфейс KeyListener и зарегистрировав
приемник событий при помощи метода addKeyListener,
приложение Java сможет работать с клавиатурой.
В рамках интерфейса KeyListener ваше приложение
должно определить три метода с именами keyPressed,
keyReleased и keyTyped. Первые два из них будут получать
управление, соответственно, при нажатии и
отпускании клавиш. Метод keyTyped вызывается в том
случае, если пользователь нажал и отпустил
клавишу или комбинацию клавиш (такую, например,
как <Alt-X>).
Всем перечисленным выше методам передается
ссылка на объект класса KeyEvent, например:
public void keyPressed(KeyEvent e)
{
. . .
}
Воспользовавшись этой ссылкой, вы сможете
получить нужную информацию о клавише, вызвавшей
возникновение события.
Внутри обработчиков keyPressed и keyReleased нетрудно
определить код нажатой или отпущенной клавиши,
воспользовавшись методом getKeyCode. Если методу
getKeyText передать значение, полученное от этого
метода, то можно получить текстовое описание
клавиши, вызвавшей событие.
Метод getKeyChar применяется внутри метода keyTyped.
Заметим, что если вы попытаетесь вызвать метод
getKeyCode из метода keyTyped, то в качестве результата
получите код неопределенной виртуальной клавиши
со значением KeyEvent.VK_UNDEFINED.
В том случае когда код клавиши нельзя
отобразить ни на один символ Unicode, метод getKeyChar
возвращает значение KeyEvent.CHAR_UNDEFINED.
В классе KeyEvent имеются определения констант для
кодов всех основных клавиш. Мы приведем только
самые необходимые (полный список есть в
документации JDK):
Константа |
Описание |
VK_0, VK_1, …, VK_9 |
Соответствуют кодам ASCII от 0 до 9
(0x30 - 0x39) |
VK_A, VK_B, …, VK_Z |
Соответствуют кодам ASCII от A до Z
(0x41 - 0x5A) |
VK_ALT |
<Alt> |
VK_BACK_QUOTE |
Обратная кавычка |
VK_BACK_SLASH |
Обратный слеш |
VK_BACK_SPACE |
Пробел |
VK_CANCEL |
Отмена |
VK_CAPS_LOCK |
<Caps Lock> |
VK_CLEAR |
Очистка |
VK_CLOSE_BRACKET |
Закрывающая скобка |
VK_COMMA |
Запятая |
VK_CONTROL |
<Control> |
VK_DECIMAL |
Десятичная точка |
VK_DELETE |
<Delete> |
VK_DIVIDE |
Деление |
VK_DOWN |
Перемещение курсора вниз |
VK_END |
<End> |
VK_ENTER |
<Enter> |
VK_EQUALS |
Равенство |
VK_ESCAPE |
<Esc> |
VK_F1, VK_F2, …, VK_F12 |
Функциональные клавиши <F1>, …,
<F12> |
VK_HELP |
Запрос подсказки |
VK_HOME |
<Home> |
VK_INSERT |
<Insert> |
VK_LEFT |
Перемещение курсора влево |
VK_MULTIPLY |
Умножение |
VK_NUM_LOCK |
<Num Lock> |
VK_NUMPAD0, VK_NUMPAD1, …, VK_NUMPAD9 |
Цифровые клавиши 0, …, 9,
расположенные на отдельной цифровой клавиатуре |
VK_OPEN_BRACKET |
Открывающая скобка |
VK_PAGE_DOWN |
<Page Down> |
VK_PAGE_UP |
<Page Up> |
VK_PAUSE |
<Pause> |
VK_PERIOD |
Точка |
VK_PRINTSCREEN |
<Print Screen> |
VK_QUOTE |
Запятая |
VK_RIGHT |
Перемещение курсора вправо |
VK_SCROLL_LOCK |
<Scroll Lock> |
VK_SEMICOLON |
Точка с запятой |
VK_SEPARATER |
Разделитель |
VK_SHIFT |
<Shift> |
VK_SLASH |
Слеш |
VK_SPACE |
Пробел |
VK_SUBTRACT |
Вычитание |
VK_TAB |
Клавиша табуляции |
VK_UP |
Перемещение курсора вверх |
Анализируя код нажатой или отжатой клавиши в
методах keyPressed и keyReleased, ваше приложение может
предпринимать те или иные действия в
соответствии с логикой работы программы. Если же
для вас важен код символа, соответствующий
нажатой клавише или комбинации клавиш,
воспользуйтесь методами keyTyped и getKeyChar.
Описание примера
Пример KeyInfo представляет собой автономное
приложение Java с окном класса Frame. Внутри этого
окна отображаются коды, а также названия
нажимаемых и отжимаемых клавиш (рис. 1).
Рис. 1. Окно приложения KeyInfo.
Рассмотрим исходный текст приложения.
Класс KeyInfo
В классе KeyInfo мы определили статический метод
main, в задачу которого входит создание объекта на
базе класса FrameWindow, определенного в нашем
приложении:
public class KeyInfo
{
public static void main(String args[])
{
FrameWindow frame;
frame = new FrameWindow("Keyboard monitor");
frame.init();
frame.show();
}
}
После создания объекта мы инициализируем его
методом init и отображаем методом show.
Класс FrameWindow
Этот класс создан нами на базе класса Frame. Для
обработки событий от клавиатуры он реализует
интерфейс KeyListener. Дополнительно этот класс также
реализует интерфейс WindowListener, что необходимо для
правильного завершения работы приложения при
удалении его окна:
class FrameWindow extends Frame
implements KeyListener, WindowListener
{
. . .
}
Поля класса FrameWindow
В классе FrameWindow мы определили всего два поля:
int yHeight;
Dimension wndDimension;
Первое из них с именем yHeight хранит высоту
символов текущего шрифта, а второе - размеры окна
приложения. Оба поля используются в процессе
свертки строк, отображаемых в окне приложения.
Конструктор класса FrameWindow
Этот конструктор достаточно прост:
public FrameWindow(String szTitle)
{
super(szTitle);
setSize(400, 400);
setBackground(Color.yellow);
setForeground(Color.black);
}
Он вызывает конструктор базового класса Frame,
устанавливает методом setSize размеры окна
приложения, а также цвет фона и текста.
Метод init класса FrameWindow
В задачу метода init класса FrameWindow входит
регистрация обработчиков событий от клавиатуры
и от главного окна приложения:
public void init()
{
this.addKeyListener(this);
this.addWindowListener(this);
}
Регистрация выполняется, соответственно,
методами addKeyListener и addWindowListener.
Метод keyPressed класса FrameWindow
Когда пользователь нажимает клавишу,
управление передается методу keyPressed,
реализованному как часть интерфейса KeyListener:
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_F3)
{
setVisible(false);
System.exit(0);
}
showKeyboardInfo(e, true);
lineFeed();
}
При помощи метода getKeyCode мы проверяем
виртуальный код нажатой клавиши. Если он равен
KeyEvent.VK_F3 (то есть соответствует функциональной
клавише <F3>), приложение завершает свою работу.
В противном случае мы вызываем метод showKeyboardInfo,
определенный в нашем приложении и отображающий в
окне приложения информацию о нажатой клавише.
Через первый параметр этому методу передается
ссылка на объект-событие, связанное с нажатой
клавишей, а через второй - значение true (признак
нажатия клавиши). Информация отображается в виде
однострочного сообщения, располагающегося в
верхней части окна.
Далее метод lineFeed, также определенный в нашем
приложении, выполняет свертку содержимого окна,
сдвигая старые сообщения на одну строку вниз.
Метод keyReleased класса FrameWindow
Исходный текст этого метода представлен ниже:
public void keyReleased(KeyEvent e)
{
showKeyboardInfo(e, false);
lineFeed();
}
Здесь мы, также как и для метода keyPressed, вызываем
методы showKeyboardInfo и lineFeed. Однако через второй
параметр методу showKeyboardInfo передается значение false
- признак того, что клавиша была отжата.
Метод keyTyped класса FrameWindow
Этот метод наше приложение не использует. Тем
не менее, мы должны его определить как составную
часть интерфейса KeyListener:
public void keyTyped(KeyEvent e)
{
}
Метод showKeyboardInfo класса FrameWindow
Прежде всего метод showKeyboardInfo получает ссылку на
контекст отображения окна приложения:
Graphics g = getGraphics();
Далее в этом контексте устанавливается шрифт с
фиксированной шириной символов Courier:
g.setFont(new Font("Courier",
Font.PLAIN, 12));
Вслед за этим метод формирует текстовую строку
s, записывая в нее виртуальный код клавиши и
текстовое описание кода клавиши:
String s = "";
s = "Code: " + e.getKeyCode() +
", " + e.getKeyText(e.getKeyCode());
Код символа определяется при помощи метода
getKeyCode, а текстовое описание - при помощи метода
getKeyText. Заметим, что в качестве параметра методу
getKeyText необходимо передать виртуальный код
клавиши, например, полученный от метода getKeyCode.
Далее метод проверяет флаг down. Если клавиша
была нажата, он равен true, если отжата - false. Мы
дописываем к переменной s соответствующую строку
и рисуем эту переменную в верхней части окна
приложения:
if(down)
s += " (press)";
else
s += " (release)";
g.drawString(s, 10, 50);
Метод lineFeed класса FrameWindow
В задачу метода lineFeed входит свертка нижней
части окна приложения после отображения
очередной строки сообщения.
Прежде всего метод lineFeed получает ссылку на
контекст отображения и выбирает в этот контекст
тот самый шрифт, который используется для
рисования сообщений:
Graphics g = getGraphics();
g.setFont(new Font("Courier",
Font.PLAIN, 12));
Далее метод получает метрики этого шрифта и
определяет высоту символов, сохраняя ее в поле
yHeight:
FontMetrics fm = g.getFontMetrics();
yHeight = fm.getHeight();
В поле wndDimension записываются размеры окна
приложения:
wndDimension = getSize();
Свертка выполняется методом copyArea:
g.copyArea(0, 1,
wndDimension.width - 1,
wndDimension.height - yHeight - 5,
0, yHeight + 1);
Здесь мы сдвигаем верхнюю часть окна
приложения вниз на размер символов шрифта Courier.
Далее верхняя часть окна, где отображаются
новые сообщения, закрашивается желтым цветом:
g.setColor(Color.yellow);
g.fillRect(1, 1,
wndDimension.width - 2,
yHeight + 1);
Метод paint класса FrameWindow
Этот метод просто вызывает метод paint из
родительского класса Frame:
public void paint(Graphics g)
{
super.paint(g);
}
Метод windowClosing класса FrameWindow
Метод windowClosing реализован нами как часть
интерфейса WindowListener:
public void windowClosing(WindowEvent e)
{
setVisible(false);
System.exit(0);
}
Он получает управление, когда пользователь
пытается закрыть окно приложения при помощи
специально предназначенной для этого кнопки
заголовка окна или комбинации клавиш.
Другие методы интерфейса WindowListener
Мы также реализовали и другие методы
интерфейса WindowListener:
public void windowOpened(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) {}
Наши реализации ничего не делают, однако
определения этих методов необходимы для полноты
интерфейса WindowListener.
Назад Вперед |