Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Портянкин И. Swing

.pdf
Скачиваний:
140
Добавлен:
07.10.2020
Размер:
4.63 Mб
Скачать

Основные концепции

25

вающий предназначение вашего приложения (конечно, это довольно долго и недешево, но всегда можно использовать внешний вид от стороннего производителя). Никто не запрещает вам создать абсолютно новаторский трехмерный интерфейс или интерфейс, основанный только на системе синтеза и распознавания речи. Причем вам не нужно будет изменять ни строчки кода в вашем приложении.

Специальные средства для пользователей с ограниченными возможностями

Практически в любой современной системе создания пользовательского интерфейса поддерживаются специальные средства для работы людей, которые по каким то причинам (травмы или болезни) не способны работать с компьютером обычным образом (они могут не видеть экран, им может быть неудобно манипулировать мышью и клавиатурой). Зачастую единственным, что связывает таких людей с окружающим миром, становится компьютер. Поэтому очень важно обеспечить приложения механизмом, позволяющим специальными средствами передавать информацию пользователям в нужном виде.

Надо сказать, что, создавая приложение с помощью Swing, вы уже выполняете большую часть работы, необходимой для поддержки специальных средств. Разработчики Swing учли важность этой поддержки и встроили во все компоненты особую информацию. Эта информация (она может быть передана специальным средствам, которые обработают ее надлежащим образом) описана во внутренних классах компонентов, использующих библиотеку Accessibility (эта библиотека относится к набору Java Foundation Classes).

Итак, в каждом компоненте библиотеки Swing имеется внутренний класс, имя которого составляется из названия класса компонента и слова «Accessible», например, в классе кнопки (JButton) имеется внутренний класс AccessibleJButton. В классах AccessibleXXX содержится исчерпывающая информация о компонентах Swing (набор «ролей», которые исполняют графические компоненты в пользовательском интерфейсе; действия, которые можно совершать над компонентом, основные свойства компонента, например, текст надписи). Если на компьютере установлено специальное средство, оно находит эту информацию (вызывая для этого метод getAccessibleContext(), встроенный в общий класс всех компонентов Swing JComponent) и выводит ее в надлежащем виде (например, для человека с расстройством зрения интерфейс будет «прочитан» путем синтеза речи). Практически все известные средства для «чтения» интерфейсов или работы через специальные устройства поддерживают библиотеку Accessibility, к примеру, известная программа JAWS.

Вся работа фактически уже сделана разработчиками Swing: например, если вы создаете кнопку с надписью (не предпринимая никаких дополнительных усилий), специальное средство сразу получит информацию о том, что в пользовательском интерфейсе программы имеется кнопка, название кнопки и данные о том, что кнопку можно «нажать». Что делать с этой информацией дальше, зависит от ситуации и от того, как именно пользователю удобно получать информацию. Самое главное здесь — это то, что вы просто пишите приложение, совершенно не задумываясь о том, что в дальнейшем оно может быть использовано человеком с ограниченными возможностями, и, тем не менее, вся необходимая информация будет на месте. Учитывая другие достоинства Swing: независимость от конкретной платформы, способность динамически менять внешний вид и поведение (что особенно важно для специальных средств, при использовании которых возможно придется увеличивать размеры компонентов, по-особому обрабатывать действия, озвучивать их), простую локализацию и поддержку Unicode, можно сказать, что для специальных средств библиотека Swing подходит как нельзя лучше.

26

ГЛАВА 1

Если вам вдруг понадобиться проверить, как Swing справляется с поддержкой специальных средств, это всегда можно сделать. Загляните на официальный сайт java.sun.com, там вы найдете несколько инструментов для тестирования, а также ссылки на реальные специальные средства с поддержкой библиотеки Accessibility.

Локализация приложений

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

Библиотека Swing великолепно справляет с задачей представления приложений на нескольких языках, во многом потому, что сам язык Java создавался как язык, способный корректно работать в таких ситуациях. Вынос всего текста, используемого в приложении, во внешние файлы .properties, поддержка этими файлами всего спектра символов Unicode, а значит всех мировых языков, хранение всех строк в самой программе как Unicode, позволяют безболезненно переводить программу на любые языки. Поддержка часовых поясов, дат, времени, чисел всех мировых культур также встроена в Java и доступна в Swing. Легко изменяемый внешний вид, реакция на действия пользователей, доступная нам благодаря подключаемому внешнему виду и поведению, позволит адаптировать или даже «замаскировать» приложение, так что его легко можно будет принять за другое, или написанное специально для определенных компаний или условий.

Все это еще раз доказывает, что удачная модель библиотеки Swing, вкупе с возможностями самого языка Java, позволяет создавать приложения самой сложной структуры и рассчитывать на их легкую поддержку и широкую масштабируемость.

Резюме

Итак, мы узнали, что основой Swing является библиотека AWT. Тем не менее, возможности библиотеки Swing гораздо богаче, к тому же она по праву «носит звание» библиотеки, полностью написанной на Java. Благодаря технологии JavaBeans в визуальных средствах разработки программ удалось упростить использование компонентов Swing и классов, поля и методы которых формируются по простым правилам. Подключаемые внешний вид и поведение компонентов, а также встроенная поддержка специальных возможностей придают Swing необычайную гибкость и избавляют нас от многих проблем и рутинной работы.

Глава 2. Модель событий

Графический пользовательский интерфейс (GUI) относится к системам, управляемым по событиям (event-driven systems). При запуске программы вы создаете пользовательский интерфейс, а затем ждете наступления некоторого события: нажатия клавиши, движения мыши или изменения компонента системы. При наступлении события программа выполняет необходимые действия, а затем снова переходит к ожиданию. Программа, использующая для создания пользовательского интерфейса библиотеку Swing, не является исключением. В этой главе мы увидим, как обрабатывать события

вSwing, и рассмотрим основные типы событий, общие для всех графических компонентов.

Для любой библиотеки пользовательского интерфейса очень важно качество используемой в ней системы обработки событий. Как бы библиотека ни была хороша внешне или функционально, неудачно реализованная обработка событий сведет все ее преимущества «на нет». Библиотека AWT из первого выпуска JDK — хороший пример. Несмотря на то, что она не блистала качеством и внешним видом компонентов, основным нападкам подвергалась именно неудачная система обработки событий, и, будь она получше, возможно, у AWT было бы более светлое будущее. Однако система обработки событий AWT была не слишком приспособлена к созданию масштабных программ — код, обрабатывающий события, находился прямо в классах компонентов: приходилось наследовать от них, искать нужное событие, пользуясь уже набившими оскомину операторами if и switch, и смешивать пользовательский интерфейс с деловой логикой программы. В итоге получалась программа, которую иногда было тяжело поддерживать и обновлять. Все это привело к тому что библиотека AWT была принята не слишком-то тепло.

Ксчастью, нам не придется возвращаться во времена старой системы обработки событий, и вспомнили мы ее лишь из уважения к истории развития библиотек пользовательского интерфейса в Java. Библиотека Swing использует систему обработки событий JavaBeans, и система эта действительно хороша. С одной стороны, она проста и понятна, с другой, предоставляет множество способов обработки событий, и вам остается лишь выбрать из них наиболее подходящий. Основным достоинством системы обработки событий Swing следует признать то, что как бы вы ни писали свою программу, какие бы способы создания интерфейса ни применяли, код, отвечающий за создание интерфейса, будет отделен от кода, обрабатывающего события. Это позволит и легко обновлять программу, и легко понимать ее.

Прежде чем перейти к описанию системы обработки событий Swing, мы узнаем, на базе какого решения она была создана. Во времена прежней системы существовало мнение, что хорошая система обработки событий в Java не будет создана до тех пор, пока

вязыке не появятся указатели на методы, что позволило бы использовать технику обратных вызовов (callbacks). Эта техника довольно характерна для обработки событий — вы передаете графическому компоненту ссылку на метод, который будет обрабатывать событие, и при возникновении этого события компонент вызывает ваш метод по полученной ссылке. Элегантное решение было найдено, когда создатели новой системы обработки событий решили использовать опыт объектно-ориентированного программирования, обратившись к шаблонам проектирования.

28

ГЛАВА 2

Наблюдатели

В программировании довольно часто возникает ситуация, когда при изменении данных в одном месте программы необходимо тут же обновить данные в другом месте программы. Если мы используем объектно-ориентированный язык программирования, это означает, что при изменении состояния одного объекта необходимо каким-либо образом изменить другой объект. Самое простое решение — организация непосредственной связи между объектами, то есть поддержание ситуации, когда объекты хорошо осведомлены о существовании друг друга. Первый объект знает, что изменение его состояния интересует другой объект, у него есть ссылка на этот объект, и каждый раз при изменении своего состояния он сообщает об этом другому объекту. В такой ситуации второй объект (получающий сообщения об изменениях) чаще всего нуждается в дополнительной информации о первом объекте (в котором происходят изменения), поэтому у него есть ссылка на первый объект. В результате получается то, что мы называем сильно связанными объектами — два объекта хранят ссылки друг на друга.

Однако это простое решение оказывается весьма ограниченным. Любое последующее изменение в программе приведет к тому, что придется основательно ее переписывать. Если изменениями в первом объекте интересуется какой-то объект, вполне возможно, что в будущем этими изменениями заинтересуется еще один объект, а потом еще несколько. Единственным способом обеспечить их информацией об изменениях в объекте станет переписывание исходного кода программы, чтобы включить в него ссылки на новые объекты. Однако делать это каждый раз при изменении количества заинтересованных объектов неудобно, долго и чревато ошибками. А если до запуска программы количество заинтересованных объектов вообще неизвестно, то наше простое решение совсем не подойдет.

Описанная ситуация встречается довольно часто, так что неудивительно, что наилучший вариант решения уже был найден в форме наблюдателя — одного из самых известных шаблонов объектно-ориентированного проектирования. Наблюдатель определяет, как следует организовать взаимоотношения между объектами, чтобы избежать сильной связи между ними и таким образом добиться необходимой гибкости. Давайте посмотрим, что этот шаблон из себя представляет.

Итак, объект, за которым ведется наблюдение, называется субъектом (subject). Объект, заинтересованный в изменениях субъекта, называются наблюдателем (observer). В обязанности субъекта входит добавление наблюдателей (в идеале количество наблюдателей произвольно), отправка наблюдателям сообщений об изменениях своего состояния и отсоединение ранее добавленных наблюдателей. Наблюдатели проще субъектов: они определяют методы, которые следует вызывать субъекту, для того чтобы сообщить о своих изменениях (рис. 2.1).

Субъект (subject) add() remove() notify()

notify() вызывает метод update()

Наблюдатель

Наблюдатель

Наблюдатель

(observer)

(observer)

(observer)

update()

update()

update()

Рис. 2.1. Взаимоотношения наблюдателей и субъектов

Модель событий

29

Рисунок показывает, что субъект обладает тремя методами: метод add() позволяет добавить очередного наблюдателя (как правило, наблюдатели хранятся в виде списка, что позволяет иметь произвольное их количество и легко манипулировать ими); метод remove() позволяет удалить ранее добавленного наблюдателя; метод notify() сообщает наблюдателям, добавленным ранее методом add(), о смене состояния субъекта. Для этого он вызывает определенный во всех объектах-наблюдателях специальный метод, в нашем случае это метод update(). В свою очередь наблюдатели знают, что очередной вызов метода update() означает смену состояния субъекта, и выполняют в этом методе все необходимые действия. Чтобы субъекты и наблюдатели смогли работать друг с другом, их функции описываются в базовых классах (или интерфейсах), и объекты, которым необходимо знать друг

одруге, но которым нежелательно быть сильно связанными, наследуют от этих базовых классов или реализуют интерфейсы и начинают работать как субъекты и наблюдатели.

Ничего сложного в субъектах и наблюдателях нет, тем не менее, они позволяют объектам просто и чрезвычайно элегантно узнавать друг о друге. Объекты, изменения в которых могут быть интересны окружающим, становятся субъектами (то есть просто поддерживают список наблюдателей), а заинтересованным в их изменениях объектам нужно лишь определить методы наблюдателей и зарегистрировать свой интерес к субъектам. Никто не запрещает субъектам самим быть наблюдателями, и наоборот. В Java субъекты и наблюдатели могут работать особенно эффективно — возможность определять внутренние классы позволяет одному классу одновременно иметь информацию

онескольких совершенно разных субъектах и эффективно обрабатывать ее.

Нетрудно заметить, что шаблон наблюдателя должен прекрасно работать в системах обработки событий, происходящих в пользовательском интерфейсе. Действительно, субъектами являются различные графические компоненты, из которых состоит интерфейс — кнопки, списки, текстовые поля, а программист определяет, что в них происходит (щелчки на кнопках, перемещения мыши), описывает объекты-наблюдатели и решает, как поступить при смене состояния интересующего его компонента. По сути, все действует по законам знакомой нам по первой главе архитектуры «модель-вид-контроллер», только на более высоком уровне. Компонент представляет собой вид, в модели хранятся данные, так, как это удобно программе, ну а наблюдатель является контроллером, только уже более высокого уровня, который определяет что будет происходить в программе в ответ на происходящие события, то есть контроллером всей программы или ее части.

Интересно, что вся библиотека Swing буквально «напичкана» субъектами и наблюдателями. Мало того, что эта концепция используется при обработке событий, она еще позволяет моделям и UI-представителям Swing иметь самую свежую информацию друг о друге. И модели, и UI-представители одновременно представляют собой субъектов и наблюдателей — при изменении данных модели она уведомляет об этом UI-представи- теля (выступающего в качестве наблюдателя), и тот обновляет внешний вид компонента в соответствии с новыми данными. Если же в ответ на действие пользователя меняется внешний вид компонента (а за это отвечает UI-представитель), то уже модель становится наблюдателем и получает уведомление о том, что данные необходимо изменить.

Но вернемся к системе обработки событий Swing. Она на самом деле основана на отношении вида субъект-наблюдатель. Субъектами являются компоненты Swing (кнопки JButton, списки JList и т. п.), а наблюдателями — специальные объекты, которые называют слушателями. Для того чтобы узнать о каком-либо событии, надо написать соответствующего слушателя и присоединить его к компоненту.

Слушатели

Событие (event) в пользовательском интерфейсе — это либо непосредственное действие пользователя (щелчок или движение мыши, нажатие клавиши), либо изменение состояния какого-либо компонента интерфейса (например, щелчок мыши может при-

30

ГЛАВА 2

вести к нажатию кнопки). Источником события (event source) в Swing может быть любой компонент, будь то кнопка, надпись с текстом или диалоговое окно. Для того чтобы узнавать в своей программе о происходящих в компоненте событиях, нам необходимо сообщить компоненту о своей заинтересованности. Сделать это можно, передав компоненту слушателя (listener) определенного события. Слушатель — этот тот самый наблюдатель (разница только в названиях), которому компонент будет сообщать о происходящих в нем событиях.

Каждому типу события соответствует свой слушатель. Так гораздо проще следить именно за теми событиями, что нас интересуют, а не за всеми подряд — код, обрабатывающий щелчки мыши, будет отделен от кода, ответственного за нажатия клавиш. Обязанности слушателей (то есть методы, которые в них должны быть определены) описаны в соответствующих интерфейсах. Вы реализуете в своем классе нужный вам интерфейс слушателя, передаете его в интересующий вас компонент и спокойно ждете наступления события. Давайте рассмотрим простой пример, в котором мы попытаемся узнать о нажатиях клавиш при активном окне.

//FirstEvents.java

//События - нажатия клавиш на клавиатуре import javax.swing.*;

import java.awt.event.*;

public class FirstEvents extends JFrame { public FirstEvents() {

super("FirstEvents");

//при закрытии окна - выход setDefaultCloseOperation(EXIT_ON_CLOSE);

//регистрируем нашего слушателя addKeyListener(new KeyL());

//выводим окно на экран

setSize(200, 200); setVisible(true);

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new FirstEvents(); } });

}

}

// этот класс будет получать извещения о событиях class KeyL implements KeyListener {

// печать символа

public void keyTyped(KeyEvent k) { System.out.println(k);

}

// нажатие клавиши

Модель событий

31

public void keyPressed(KeyEvent k) { System.out.println(k);

}

// отпускание нажатой клавиши

public void keyReleased(KeyEvent k) { System.out.println(k);

}

}

Пример очень прост — мы создаем класс, унаследованный от окна JFrame, устанавливаем для него размер методом setSize(), указываем, что при закрытии окна следует завершить работу приложения (методом setDefaultCloseOperation(), подробнее об этом методе мы узнаем в главе 4, посвященной окнам) и выводим окно на экран. Правда сам запуск приложения происходит через некий таинственный класс SwingUtilities, однако такова архитектура Swing. Очень скоро мы узнаем, почему не стоит вызывать конструктор окна напрямую, а сейчас гораздо интереснее посмотреть, как создается слушатель события.

Прежде всего, необходимо написать класс, реализующий интерфейс слушателя. Если вы просмотрите интерактивную документацию Java, то увидите, что для получения информации о нажатиях клавиш используется интерфейс KeyListener, именно его мы и реализовали в классе KeyL. В этом интерфейсе определены три метода, каждый из которых вызывается при наступлении определенного события: keyPressed() и keyReleased() — при нажатии и отпускании клавиши, keyTyped() — при печати символа (когда нажимается и отпускается клавиша, соответствующая печатному символу1). В качестве параметра каждому методу передается объект KeyEvent, который используется для получения дополнительной информации о событии (кода клавиши, источника события и т. д.). Чтобы сделать программу максимально простой, мы просто передаем эту информацию в стандартный поток вывода.

Последний этап — регистрация нашего слушателя в интересующем нас компоненте. Компонент у нас в программе только один — это наше окно. Для регистрации слушателя событий от клавиатуры мы вызываем метод addKeyListener(), в который передаем ссылку на объект класса KeyL. После этого остается только запустить программу

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

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

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

1 Метод keyTyped() — более высокого уровня, чем остальные два слушателя KeyListener. Он сообщает программе, что пользователь нажал и отпустил или удерживает клавишу с печатным символом (печатные символы — это все буквы, цифры, а также пробел и клавиши Enter и Esc), однако эти печатные символы могут не иметь точного отображения на одну клавишу клавиатуры, в то время как другие два метода сообщают именно о нажатии физических клавиш.

32

ГЛАВА 2

Схема именования событий JavaBeans

Система обработки событий в Swing является частью архитектуры JavaBeans, которая позволяет создавать переносимые и легко используемые графические компоненты для визуальных средств разработки программ. В главе 1 мы узнали, что все компоненты Swing являются компонентами JavaBeans. Как вы помните, основой JavaBeans является соглашение об именах, которое позволяет визуальным средствам легко узнавать, какими свойствами обладает компонент. Для этого компонент определяет набор методов со специальными именами get/set. Методы эти служат для считывания и записи значений свойств компонента.

События в JavaBeans обрабатываются с помощью слушателей; как это происходит, мы только что увидели. Нетрудно понять, что для того чтобы визуальное средство смогло определить, какие события могут возникать в компоненте, также необходим какой-то механизм для выявления этих событий. Таким механизмом является специальная схема именования событий и обрабатывающих их слушателей.

У каждого события есть имя. Например, в примере из предыдущего раздела этим именем было слово «Key» (клавиша) — неудивительно, ведь это событие происходит при нажатии клавиш на клавиатуре. События, которые происходят в окнах, называются «Window» (окно); в общем случае будем считать, что названием события являются просто символы «XXX». Чтобы событие стало доступно визуальному средству разработки, необходимо проделать описанную ниже процедуру.

1.Определить класс, в котором будет храниться информация о произошедшем событии (что это будет за информация, определяет создатель события). Класс должен быть унаследован от базового класса java.util.EventObject и иметь название вида XXXEvent, где «XXX» — это название нашего события. В предыдущем примере мы видели, что информация о событиях от клавиатуры хранилась в классе с названием KeyEvent.

2.Создать интерфейс слушателя, в который будет приходить информация о событии. Это должен быть именно интерфейс, а не класс. Название интерфейса должно иметь следующий вид: XXXListener — в предыдущем примере мы использовали слушателя с именем KeyListener. Этот интерфейс должен быть унаследован от базового интерфейса всех слушателей событий java.util.EventListener (это пустой интерфейс без методов, он просто помечает то, что унаследованный от него интерфейс является слушателем). В интерфейсе может быть определено сколь угодно много методов, единственное требование к этим методам — наличие параметра типа XXXEvent. Никаких других параметров у методов быть не должно.

3.Включить поддержку события в класс компонента, в котором это событие может происходить. Чтобы сделать это, необходимо определить два метода: один для присоединения слушателей, другой для их отсоединения. Названия методов должны выглядеть следующим образом: addXXXListener() — для метода, присоединяющего слушателей, и removeXXXListener() — для метода, отсоединяющего слушателей. Если вспомнить пример, то там присоединение слушателя происходило как раз с помощью метода addKeyListener(), определенного в классе окон JFrame (на самом деле этот метод определен в базовом классе всех компонентов Component, и добавлять слушателей клавиатуры можно к любому компоненту).

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

Модель событий

33

мечали, насколько JavaBeans упрощает создание компонентов. Сейчас для нас гораздо важнее то, что, зная правила, по которым создаются события JavaBeans (а компоненты Swing используют именно эти события), мы можем очень просто определить всю интересующую информацию о событии, не перерывая документацию. Предположим, нам захотелось узнать, что происходит в окне нашего приложения. Скорее всего, события, происходящие в окнах, описаны в классе WindowEvent. Если это так, то согласно схеме именования нам нужно реализовать интерфейс WindowListener и зарегистрировать его в нашем окне с помощью метода addWindowListener(). Как оказывается, именно такие классы и интерфейсы позволяют обрабатывать оконные события, и, хотя мы не знали об этом, а просто предполагали, наши предположения полностью подтвердились!

Система обработки событий JavaBeans удивительно прозрачна и понятна: достаточно один раз понять простые принципы, лежащие в ее основе, как она мгновенно становится совершенно незаменимым инструментом в работе, помогающим справиться с большинством проблем, которые возникают при обработке событий.

Стандартные события

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

Надо сказать, что события в Java условно разделяются на низкоуровневые (low-level events) и высокоуровневые (high-level events). К низкоуровневым событиям относят те, что происходят непосредственно в результате действий пользователя: это движения мыши, передача фокуса ввода от одного приложения другому, нажатия клавиш и т. п.2 Они поступают в Java-программу от операционной системы или от внутренних механизмов виртуальной машины. Высокоуровневые события происходят в результате изменения состояния компонента. Такие события поступают не от операционной системы, а создаются самим компонентом. Процесс создания события еще называют запуском (fire). Во многих компонентах Swing вы можете увидеть методы с именами вида fireXXX(); именно в таких методах создаются объекты с информацией о событиях, которые затем рассылаются слушателям. Часто события высокого уровня возникают после того, как происходят несколько событий низкого уровня (например, кнопка сообщает о своем нажатии, после того как над ней была нажата и отпущена кнопка мыши).

Начнем мы с низкоуровневых событий (табл. 2.1). Эти события могут возникать в любом графическом компоненте, унаследованном от класса java.awt.Component (правда, есть несколько исключений).

Таблица 2.1. Основные низкоуровневые события

Краткое описание события

Методы слушателя

Источник события

Событие от клавиатуры.

keyPressed(KeyEvent),

Все компоненты (на-

Описано в классе KeyEvent.

keyReleased(KeyEvent),

следники класса java.

Возникает, когда пользователь

keyTyped(KeyEvent)

awt.Component)

нажимает клавишу

 

 

2 Низкоуровневые события легко отличить от высокоуровневых — все они унаследованы от особого базового класса AWTEvent.

34

 

ГЛАВА 2

Таблица 2.1 (продолжение)

 

 

 

 

 

Краткое описание события

Методы слушателя

Источник события

Нажатия и отпускания кнопок

mouseClicked(MouseEvent),

Все компоненты

мыши и попадание курсора

mouseEntered(MouseEvent),

 

в область компонента. Класс

mouseExited(MouseEvent),

 

MouseEvent позволяет следить

mousePressed(MouseEvent),

 

за состоянием кнопок мыши

mouseReleased(MouseEvent)

 

и контролировать нахождение

 

 

указателя мыши в определен-

 

 

ной области

 

 

Перемещение мыши. Класс

mouseDragged(MouseEvent),

Все компоненты

события тот же — Mouse-

mouseMoved(MouseEvent)

 

Event, но вот слушатель

 

 

называется по-другому —

 

 

MouseMotionListener3

 

 

Прокрутка колесика мыши.

mouseWheelMoved(MouseWheelEvent)

Все компоненты

Класс MouseWheelEvent

 

 

Передача фокуса ввода. Класс

focusGained(FocusEvent),

Все компоненты

FocusEvent

focusLost(FocusEvent)

 

Добавление или удаление

componentAdded(ContainerEvent),

Все контейнеры (на-

компонентов в контейнере.

componentRemoved(ContainerEvent)

следники класса java.

Класс ContainerEvent

 

awt.Container)

Изменения состояния окна.

windowActivated(WindowEvent),

Окна (наследники

Класс WindowEvent. Позволяет

windowClosed(WindowEvent),

класса java.awt.

узнать о перемещении, сверты-

windowClosing(WindowEvent),

Window), напри-

вании, закрытии окна и т. д.

windowDeactivated(WindowEvent),

мер, окна с рамкой

 

windowDeiconified(WindowEvent),

(JFrame) или диало-

 

windowIconified(WindowEvent),

говые окна (JDialog)

 

windowOpened(WindowEvent)

 

Вы видете, что в таблице нет названий слушателей и методов, предназначенных для добавления и удаления этих слушателей. Такие названия легко получить самим: достаточно вспомнить простые правила именования, которые мы рассмотрели в предыдущем разделе. Используя данную таблицу, можно написать слушатель для любого низкоуровневого события (в таблице описаны не все, а только наиболее важные низкоуровневые события; компоненты поддерживают еще несколько событий, которые используются крайне редко, вы можете познакомиться с ними в интерактивной документации). 3

Чтобы окончательно убедиться в том, что события эти на самом деле возникают,

икомпоненты сообщают о них слушателям, рассмотрим небольшой пример:

//LowLevelEvents.java

//Наблюдение за основными низкоуровневыми событиями import javax.swing.*;

import java.awt.event.*; import java.awt.*;

3 Это единственное исключение из правила именования событий JavaBeans. По идее, для класса MouseEvent слушатель должен был бы называться MouseListener (как в предыдущей строке таблицы), но разработчики решили разбить этот слушатель на два.