Java. Полное руководство. 8-е издание. С. Н. Тригуб Перевод с английского и редакция
Скачать 25.04 Mb.
|
ГЛАВА Обработка событий Настоящая глава посвящена важнейшему аспекту Java — событиям. Обработка событий является фундаментальной для всего программирования Java, поскольку это — основа аплетов и прочих типов программ с графическим пользовательским интерфейсом (Graphical User Interface — GUI). Как упоминалось в главе 22, аплеты представляют собой управляемые событиями программы, использующие графический интерфейс для взаимодействия с пользователем. Более того, любая программа с графическим пользовательским интерфейсом, такая как приложение Java, написанное для Windows, является управляемой событиями. Другими словами, вы не можете написать такую программу без четкого представления об обработке событий. События поддерживаются множеством пакетов, включая j a v a . u t i l , j a v a . awt и j a v a . e v e n Большинство событий, на которые будет реагировать ваша программа, происходят при взаимодействии пользователя с программой на основе GUI. Именно события такого рода и рассматриваются в настоящей главе. События попадают в вашу программу множеством различных путей, каждый из которых зависит от конкретного события. Существует несколько типов событий, включая создаваемые мышью, клавиатурой и различными элементами управления GUI, такими как кнопка, полоса прокрутки или флажок. Мы начнем эту главу с обзора механизма управления событиями Java. Затем рассмотрим основные классы и интерфейсы событий, используемые библиотекой AWT, и разработаем несколько примеров, демонстрирующих основы обработки событий. Эта глава также расскажет о том, как использовать классы адаптеров, вложенные классы и анонимные вложенные классы, чтобы упростить код обработки событий. Примеры, приведенные в остальной части книги, будут использовать эти приемы. На заметку Материал зтой главы основан на событиях, имеющих отношение к программам на основе GUI. Но иногда события также используются в целях, не имеющих прямого отношения к программам подобного рода. Тем не менее во всех случаях применяются одни и те же приемы обработки событий. Прежде чем приступить к обсуждению обработки событий, сделаем одно важное замечание. Способ обработки событий существенно изменился от исходной версии Java (1.0) до более современных версий, начиная с 1.1. Метод обработки событий, принятый в версии 1.0, все еще поддерживается, хотя и не рекомендован для применения в новых программах. К тому же многие методы, поддерживающие старую модель событий 1.0, теперь объявлены устаревшими (deprecated). Современный подход состоит в том, что события должны обрабатываться всеми программами так, как описано в этой книге. Два механизма обработки событий Модель делегирования событий Современный подход к обработке событий основан на модели делегирования событий (delegation event m odel), определяющей стандартные и согласованные механизмы для создания и обработки событий. Его концепция проста источник извещает о событии одного или несколько слушателей (listener). В этой схеме слушатель просто ожидает до тех пор, пока не получит извещение о событии. Как только извещение о событии получено, слушатель обрабатывает его и возвращает управление. Преимущество такого дизайна в том, что логика приложения, обрабатывающего события, четко отделена от логики пользовательского интерфейса, извещающего об этом событии. Элемент пользовательского интерфейса может делегировать обработку события отдельному фрагменту кода. В модели делегирования событий слушатели должны регистрироваться источником для того, чтобы получать извещения о событиях. Это обеспечивает важное преимущество уведомления посылаются только тем слушателям, которые желают получать их. Это более эффективный способ обработки событий, нежели тот, что был принят в старом подходе Java 1.0. Раньше извещение о событии распространялось по всей иерархии вложенности до тех пор, пока не было обработано компонентом. Это вынуждало все компоненты получать извещения о событии, которые они могли и не обрабатывать, что приводило к значительным затратам времени. Модель делегирования событий исключила подобную расточительность. В последующих разделах определим события и опишем роли источников и слушателей 1 8 Часть II. Библиотека На заметку также позволяет обрабатывать события без применения модели делегирования. Это может быть сделано при помощи расширения компонента библиотеки AWT. Такая техника обсуждается в конце главы 25. Однако модель делегирования событий более предпочтительна по описанным выше причинам. События В модели делегирования событие это объект, описывающий изменение состояния источника. Он может быть создан в результате взаимодействия пользователя с элементом графического интерфейса. К событиям приводят такие действия, как щелчок на экранной кнопке, ввод символа с клавиатуры, выбор элемента в списке и щелчок кнопкой мыши. Многие другие пользовательские операции также могут служить подобными примерами. События могут также происходить и не в результате прямого взаимодействия с пользовательским интерфейсом. Например, событие может произойти по истечении времени таймера в результате превышения счетчиком некоторого значения, программного или аппаратного сбоя либо завершения некоторой операции. Вы можете определять собственные события, отвечающие специфике вашего приложения. Источники событий Источник (source) — это объект, извещающий о событии. Событие происходит при изменении внутреннего состояния объекта некоторым образом. Источники могут извещать о событиях нескольких типов. Источник должен регистрировать слушателей, чтобы они получали извещение о событиях определенного рода. Каждый тип события имеет собственный метод регистрации. Вот его общая форма Глава 23. Обработка событий 1 9 public void add№n L i s t e n e r (Тип Здесь Тип имя события, a e l — ссылка на слушателя событий. Например, метод, регистрирующий слушателя событий клавиатуры, называется addKey- Listener(), а метод, регистрирующий слушателя движения мыши, — add- MouseMotionListener() . Когда событие происходит, все зарегистрированные слушатели получают копию объекта события. Это называется групповой рассылкой (multicasting) события. Во всех случаях уведомления отправляются только тем слушателям, которые зарегистрированы на их получение. Некоторые источники допускают регистрацию только одного слушателя. Общая форма такого метода показана ниже void addTnrrLi st ener ( TnnList ener el) throws j a v a .u t i l Здесь Тип это имя объекта события, a e l — ссылка на слушателя события. Когда такое событие происходит, зарегистрированный слушатель получает уведомление. Это называется индивидуальной рассылкой (unicasting) события. Источник должен также предоставлять метод, позволяющий слушателю отменить регистрацию для определенного типа событий. Общая форма этого метода такова void remove TnriList ener ( TtoListener И снова Тип это имя объекта события, a e l — ссылка на слушателя события. Например, чтобы удалить слушателя клавиатуры, следует вызвать метод remove- Метод, который добавляет или удаляет слушателей, предоставляется источником, извещающим о событии. Например, класс Component предлагает методы для добавления и удаления слушателей клавиатуры и мыши. Слушатели событий Слушатель (listener) — это объект, уведомляемый о событии. К нему предъявляются два основных требования. Во-первых, он должен быть зарегистрирован одним или более источниками событий, чтобы получать уведомления о событиях определенного рода. Во-вторых, он должен реализовать методы для получения и обработки таких уведомлений. Методы, принимающие и обрабатывающие события, определены в наборе интерфейсов, находящихся в пакете j ava. awt. event. Например, интерфейс Мои определяет два метода для получения уведомлений о перетаскивании объекта или перемещении мыши. Любой объект может принимать и обрабатывать одно или оба эти события, если предоставляет реализацию этого интерфейса. В этой и последующих главах мы еще поговорим о многих других интерфейсах слушателей. Классы событий Классы, представляющие события, находятся в ядре механизма обработки событий Java. А потому дискуссия об обработке событий должна начинаться с классов событий. Важно понимать, однако, что Java определяет несколько типов событий и что не все классы событий будут упомянуты в настоящей главе. Наиболее широко используемыми событиями являются те, что определены библиотеками AWT и Swing. Здесь сосредоточимся на событиях библиотеки AWT. Многие из них относятся также и к библиотеке Swing.) Несколько специф ич 7 2 Часть II. Библиотека Java ных для библиотеки Swing событий будут описаны в главе 30, когда речь пойдет библиотеке В корне иерархии классов событий Java лежит класс EventObject, расположенный в пакете j ava .util. Это — суперкласс для всех событий. Его единственный конструктор выглядит следующим образом источник) Параметр источник здесь представляет объект, извещающий о событии. Класс EventObject содержит два метода get Source () и toString ( ). Метод get Source () возвращает источник события. Его общая форма такова ect Как можно ожидать, метод toString () возвращает строку — эквивалент со бытия. Класс AWTEvent, определенный в пакете java. awt, рассматривается в конце главы 25. А пока важно знать, что все классы, о которых пойдет речь в этом разделе, являются подклассами класса AWTEvent. Итак, подытожим. • Класс EventObj ect — суперкласс для всех событий. • Класс AWTEvent — суперкласс всех событий библиотеки AWT, обрабатываемых моделью делегирования событий. Пакет j ava. awt. event определяет множество типов событий, происходящих во многих элементах пользовательского интерфейса. В табл. 23.1 показано несколько широко используемых классов событий и представлено краткое описание того, когда они происходят. Наиболее часто используемые конструкторы и методы каждого класса описаны в последующих разделах. Таблица 2 3 . 1 . Основные классы событий в пакете j a v a . a w t . e v e n t Кдасссоботия Описание _______ ‘_____________ ______________ Act ionEvent Происходит при нажатии кнопки, двойном щелчке на элементе списка либо выборе пункта меню j us tment Event Происходит при манипуляциях с полосой прокрутки Event Происходит при сокрытии компонента, его перемещении, изменении его размера либо включении видимости Происходит при добавлении или исключении компонента контейнера Происходит, когда компонент получает или теряет фокус клавиатурного ввода при Event Абстрактный суперкласс для всех классов ввода компонентов emEvent Происходит при щелчке на флажке или элементе списка, а также при выборе элемента списка и выборе или отмене выбора пункта меню Происходит при получении ввода с клавиатуры М о и seEvent Происходит при перетаскивании, перемещении, щелчках, нажатии и отпускании кнопок мыши также происходит, когда курсор мыши наводится на компонент либо покидает его Event Происходит при прокрутке колесика мыши Event Происходит при изменении значения текстовой области или текстового поля Происходит при активизации либо закрытии окна, а также при деакти визации, свертывании, развертывании окна или выходе из него Глава 23. Обработка событий 2 Класс A c t i o n E v e n Объект класса ActionEvent создается при нажатии кнопки, двойном щелчке на элементе списка либо при выборе пункта меню. Класс Ac t i onEven t определяет четыре целочисленные константы, которые могут быть использованы для идентификации любых модификаторов, ассоциированных с событием действия, — ALT_ MASK, CTRL_MASK, META_MASK и SHIFT_MASK. Кроме того, имеется целочисленная константа ACTION_PERFORMED,< которая может служить для идентификации событий действия. Класс ActionEvent имеет три конструктора источник int тип String команда источник int тип String команда модификаторы источник int тип String команда когда b,bbintbмодифика торы) Здесь источник это ссылка на объект, извещающий о событии. Тип события указан параметром типа его командная строка — параметром команда Аргумент модификаторы указывает на нажатие модифицирующих клавиши или) в момент события. Вы можете получить имя команды для вызывающего объекта класса Action Event, используя метод getAct ionCommand () , показанный ниже Например, при щелчке на кнопке происходит событие действия, которое имеет имя команды, соответствующее метке экранной кнопки. Метод getModif iers () возвращает значение, указывающее на то, какие модифицирующие клавиши ( get When () возвращает время, когда произошло событие. Это называется временной меткой события. Метод getWhen () выглядит следующим образом Класс A d j u s t m e n t E v e n Событие класса Adjustment Event передается полосой прокрутки. Существует пять типов событий настройки (adjustm ent). Класс Adjustment Event определяет целочисленные константы, которые могут использоваться для идентификации. Константы и их описания представлены в табл. Таблица 23.2. Константы, определенные классом d j u s t m e n t E v e n t Константа Описание BLOCK_DECREMENT Пользователь щелкнул внутри полосы прокрутки для уменьшения ее значения BLOCK_INCREMENT Пользователь щелкнул внутри полосы прокрутки для увеличения ее значения TRACK Передвинут бегунок полосы UNIT_DECREMENT Был выполнен щелчок на кнопке в конце полосы для уменьшения ее значения UNIT_INCREMENT Был выполнен щелчок на кнопке в конце полосы для увеличения ее значения 7 2 2 Часть II. Библиотека Кроме того, имеется также целочисленная константа ADJUSTMENT_VALUE_ CHANGED, которая указывает на то, что произошло изменение. Вот единственный конструктор класса AdjustmentEvent. AdjustmentEvent(Adjustable источник int идентификатор int тип int данные) Здесь источник ссылка на объект, извещающий о событии. Параметр идентификатор определяет событие. Тип настройки указан параметром типа ассоциированные с ней данные — параметром данные. Метод getAdj us table () возвращает объект, извещающий о событии. Его форма представлена ниже Тип события настройки может быть получен методом getAdj us tmentType (). Он возвращает одну из констант, определенных классом AdjustmentEvent. Его общая форма такова Величина настройки может быть получена методом getValue () , показанным ниже Например, когда выполняются манипуляции с полосой прокрутки, этот метод возвращает значение, представленное изменением. Класс C o m p o n e n t E v e n Объект класса ComponentEvent создается при изменении размера, положения или видимости компонента. Существует четыре типа событий компонентов. Для их идентификации класс ComponentEvent определяет целочисленные константы. Константы и их описания представлены в табл. Таблица 23.3. Константы, определенные классом C o m p o n e n t E v e n t Константа Описание , - . 'А ' -Компонент скрыт C0MP0NENT_M0VED Компонент перемещен C0MP0NENT_RESIZED Изменен размер компонента C0MP0NENT_SH0WN Компонент стал видимым Класс ComponentEvent имеет следующий конструктор источник int тип) Здесь источник ссылка на объект, извещающий о событии. Тип события указан параметром тип. Класс ComponentEvent — это прямой или непрямой суперкласс для классов, KeyEvent, MouseEvent, WindowEvent и др. Метод getComponent () возвращает компонент, извещающий о событии. Выглядит он так Класс C o n t a i n e r E v e n Объект класса ContainerEvent создается при добавлении компонента в контейнер или его удалении оттуда. Существует два типа событий контейнера. Класс Глава 23. Обработка событий 2 3 ContainerEvent определяет целочисленные константы, которые могут использоваться для его идентификации, — COMPONENT_ADDED и COMPONENT_REMOVED. Они определяют, добавлен ли компонент к контейнеру или же исключен из него. Класс ContainerEvent — это подкласс класса Component Event, имеющий следующий конструктор источник int тип Component компаратор) Здесь источник — ссылка на контейнер, который известило событии. Тип события указан параметром типа компонент, добавляемый в контейнер либо удаляемый из него, — параметром компаратор. Вы можете получить ссылку на контейнер, создавший это событие, из метода getContainer () , показанного ниже Метод getChild( ) возвращает ссылку на компонент, который был добавлен или удален из контейнера. Его общая форма такова Класс F o c u s E v e n Объект класса FocusEvent создается при получении или потере компонентом фокуса. Эти события определяются целочисленными константами FOCUS_GAINED и Класс FocusEvent — это подкласс класса Component Event, имеющий следующие конструкторы источник int тип источник int тип boolean временныйФлаг) FocusEvent(Component источник int тип boolean временныйФлаг, Component ' другое) Здесь источник — это ссылка на компонент, извещающий о событии. Тип события указан параметром тип. Аргумент временныйФлаг установлен в состояние true, если событие фокуса является временным. В противном случае он устанавливается в состояние false. Событие временного фокуса происходит в результате другой операции пользовательского интерфейса. Например, предположим, что фокус находится на текстовом поле. Если пользователь перемещает мышь, чтобы подвинуть полосу прокрутки, то фокус временно тёряется.) Другой компонент, участвующий в изменении фокуса и называемый противоположным компонентом, передается параметром другое. Таким образом, если происходит событие |