Java — Java выбор фокуса для KeyListener


Содержание

События и слушатели

Событие Event — это объект, описывающий изменение состояния источника, с которым оно связано. Примером события, в котором участвует пользователь, являются нажатие кнопки, выбор элемента из списка, ввод символа с клавиатуры и т.д. Событие может происходить и без участия пользователя при использовании таймера.

Слушатель Listener — это уведомляемый о некотором событии объект. Чтобы слушатель смог реагировать на определенное событие источника он должен быть им зарегистрирован, т.е. подключен к источнику. Listener должен реализовывать определенные методы для получения и обработки уведомлений о событии.

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

После обработки события слушатель возвращает управление. Таким образом, для обработки события вызываются только те слушатели, которые на него «подписались», т.е. были зарегистрированы источником.

Типы событий и слушателей

В пакете java.awt.event определены интерфейсы слушателей для каждого из определенных в нем типов событий (например, для событий MouseEvent определено два интерфейса слушателей: MouseListener и MouseMotionListener). Все интерфейсы слушателей событий являются расширениями интерфейса java.util.EventListener. В этом интерфейсе не определяется ни один из методов, но он играет роль базового интерфейса, в котором однозначно определены все слушатели событий как таковые.Т.е. слушатель наследуется от интерфейса EventListener и предназначен для обработки определенного типа событий. При этом Listener содержит один или несколько методов, которые принимают объект события в качестве единственного параметра и вызываются в определенных ситуациях.

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

В таблице приведены определенные в пакете java.awt.event типы событий, соответствующие им слушатели, а также методы, определенные в каждом интерфейсе слушателя.

Класс события Интерфейс слушателя Обработчики события
ActionEvent ActionListener actionPerformed(ActionEvent e)
AdjustmentEvent AdjustmentListener adjustmentValueChanged(AdjustmentEvent e)
ComponentEvent ComponentListener componentResized(ComponentEvent e)
componentMoved(ComponentEvent e)
componentShown(ComponentEvent e)
componentHidden(ComponentEvent e)
ContainerEvent ContainerListener componentAdded(ContainerEvent e)
componentRemoved(ContainerEvent e)
FocusEvent FocusListener focusGained(FocusEvent e)
focusLost(FocusEvent e)
ItemEvent ItemListener itemStateChanged(ItemEvent e)
KeyEvent KeyListener keyPressed(KeyEvent e)
keyReleased(KeyEvent e)
keyTyped(KeyEvent e)
MouseEvent MouseListener mouseClicked(MouseEvent e)
mousePressed(MouseEvent e)
mouseReleased(MouseEvent e)
mouseEntered(MouseEvent e)
mouseExited(MouseEvent e)
MouseMotionListener mouseDragged(MouseEvent e)
mouseMoved(MouseEvent e)
TextEvent TextListener textValueChanged(TextEvent e)
WindowEvent WindowListener windowOpened(WindowEvent e)
windowClosing(WindowEvent e)
windowClosed(WindowEvent e)
windowIconified(WindowEvent e)
windowDeiconified(WindowEvent e)
windowActivated(WindowEvent e)

Корнем иерархии классов событий является суперкласс EventObject из пакета java.util. Данный класс содержит два метода: getSource(), возвращающий источник событий, и toString(), возвращающий строчный эквивалент события. Чтобы узнать, в каком объекте произошло событие, нужно вызвать метод getSource(), возвращающий значение типа object. Следовательно, один и тот же слушатель можно подключить к разным источникам.

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

Для каждого интерфейса слушателей событий, содержащего несколько методов, в пакете java.awt.event определен класс-адаптер Adapter. Когда нужен только один или два таких метода, иногда проще получить подкласс класса-адаптера, чем реализовать интерфейс самостоятельно. При использовании адаптера требуется лишь переопределить те методы, которые нужны, а при прямой реализации интерфейса необходимо определить все методы, в том числе и ненужные в данной программе.

Заранее определенные классы-адаптеры называются также, как и интерфейсы, которые они реализуют. Но в этих названиях Listener заменяется на Adapter; например MouseAdapter, MouseMotionAdapter, WindowAdapter и т.д.

Описание класса-адаптера действий с мышью, MouseAdapter

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

События, связанные с визуальными компонентами AWT

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

Компонент Событие Описание
Button ActionEvent Пользователь нажал кнопку
CheckBox ItemEvent Пользователь установил или сбросил флажок
CheckBoxMenuItem ItemEvent Пользователь установил или сбросил флажок рядом с пунктом меню
Choice ItemEvent Пользователь выбрал элемент списка или отменил его выбор
Component ComponentEvent Элемент либо перемещен, либо он стал скрытым, либо видимым
FocusEvent Элемент получил или потерял фокус ввода
KeyEvent Пользователь нажал или отпустил клавишу
MouseEvent Пользователь нажал или отпустил кнопку мыши, либо курсор мыши вошел или покинул область, занимаемую элементом, либо пользователь просто переместил мышь или переместил мышь при нажатой кнопке мыши
Container ContainerEvent Элемент добавлен в контейнер или удален из него
List ActionEvent Пользователь выполнил двойной щелчок мыши на элементе списка
ItemEvent Пользователь выбрал элемент списка или отменил выбор
MenuItem ActionEvent Пользователь выбрал пункт меню
Scrollbar AdjustmentEvent Пользователь осуществил прокрутку
TextComponent TextEvent Пользователь внес изменения в текст элемента
TextField ActionEvent Пользователь закончил редактирование текста элемента
Window WindowEvent Окно было открыто, закрыто, представлено в виде пиктограммы, восстановлено или требует восстановления

Регистрация слушателя Listener

Для регистрации слушателя источник использует специальные методы. Как правило, имена методов имеют форму addXxxListener(XxxListener listener) или setXxxListener(XxxListener listener), где Xxx — это имя события, а listener — ссылка на слушателя событий.

Пример использования слушателя ActionListener

Интерфейс приложения представлен на рисунке.

Программный вызов события

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

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

После нажатия на кнопку button3 в консоли будет выведена следующая информация :

Невосприимчивый KeyListener для JFrame

75 Tomek [2008-11-13 13:17:00]

Я пытаюсь реализовать KeyListener для моего JFrame . В конструкторе я использую этот код:

Когда я запустил его, сообщение test появляется в моей консоли. Однако, когда я нажимаю клавишу, я не получаю никаких других сообщений, как будто KeyListener там даже не было.

Я думал, что это может быть потому, что фокус не на JFrame
и поэтому они KeyListener не получают никаких событий. Но, я уверен, что это так.

Есть ли что-то, что мне не хватает?

java swing jframe keylistener

12 ответов

45 Решение bruno conde [2008-11-13 16:01:00]


Вы должны добавить свой keyListener для каждого компонента, который вам нужен. Эти компоненты будут отправлять только компонент с фокусом. Например, если в вашем JFrame есть только один TextBox, то TextBox имеет фокус. Поэтому вы также должны добавить KeyListener к этому компоненту.

Примечание. Некоторые компоненты не настраиваются, как JLabel.

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

123 Peter [2009-09-04 17:09:00]

Если вы не хотите регистрировать слушателя на каждом компоненте,
вы можете добавить свой KeyEventDispatcher в KeyboardFocusManager :

15 Nathan [2013-02-23 03:29:00]

InputMaps и ActionMaps были предназначены для захвата ключевых событий для компонента, его и всех его подкомпонентов или всего окна. Это контролируется с помощью параметра в JComponent.getInputMap(). См. Как использовать привязки клавиш для документации.

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

Этот код будет вызывать dispose() в JFrame, когда ключ побега попадает в любом месте окна. JFrame не является результатом JComponent, поэтому вам нужно использовать другой компонент в JFrame для создания привязки ключа. Область содержимого может быть таким компонентом.

10 [2009-04-27 18:30:00]

У меня такая же проблема, пока я не прочитал, что настоящая проблема связана с FOCUS, что ваш JFrame уже добавил Listeners, но кадр тура никогда не фокусируется на фокусе, потому что у вас есть много компонентов внутри вашего JFrame, которые также можно сфокусировать, поэтому попробуйте:

KeyListener является низким уровнем и применяется только к одному компоненту. Несмотря на попытки сделать его более удобным, JFrame создает ряд компонентных компонентов, наиболее очевидным из которых является область содержимого. JComboBox Пользовательский интерфейс также часто реализуется аналогичным образом.

Стоит отметить, что события мыши работают странным образом, немного отличающимся от ключевых событий.

Подробнее о том, что вы должны сделать, см. мой ответ на Широкоэкранный набор приложений — Java Swing.

8 Daves [2011-01-09 17:50:00]

Deion (и кто-то еще задает аналогичный вопрос), вы можете использовать вышеприведенный код Peter, но вместо печати на стандартный вывод вы тестируете key code PRESSED, RELEASED или TYPED.

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

3 Touko [2008-11-13 13:39:00]

Хм.. для какого класса ваш конструктор? Возможно, какой-то класс расширяет JFrame? Фокус окна должен быть в окне, конечно, но я не думаю, что проблема.

Я расширил ваш код, попытался запустить его, и он сработал — нажатия клавиш были получены в результате вывода на печать. (запустите с помощью Ubuntu через Eclipse):

3 Rahul [2014-06-27 18:20:00]

Это должно помочь

У меня была такая же проблема. Я последовал за советом Бруно и обнаружил, что добавление KeyListener только к «первой» кнопке в JFrame (то есть в левом верхнем углу) сделало трюк. Но я согласен с вами, что это своего рода тревожное решение. Поэтому я пошарил и обнаружил более аккуратный способ исправить ситуацию. Просто добавьте строку

к вашему основному методу после создания вашего экземпляра вашего подкласса JFrame и его отображения.

-1 Chris [2012-07-10 22:24:00]

lol. все, что вам нужно сделать, это убедиться, что

правильно помещается в ваш код.

-1 Denizen [2012-11-09 23:22:00]

У вас могут быть настраиваемые JComponents, которые устанавливают родительский JFrame.

Просто добавьте конструктор и перейдите в JFrame. Затем сделайте вызов setFocusable() в paintComponent.

Таким образом, JFrame всегда будет получать KeyEvents, независимо от того, нажаты ли другие компоненты.

How to Write a Focus Listener

Focus events are fired whenever a component gains or loses the keyboard focus. This is true whether the change in focus occurs through the mouse, the keyboard, or programmatically. To get familiar with basic focus concepts or to obtain detailed information about focus, see How to Use the Focus Subsystem.

This section explains how to get focus events for a particular component by registering a FocusListener instance on it. To get focus for a window only, implement a WindowFocusListener instance instead. To obtain the focus status of many components, consider implementing a PropertyChangeListener instance on the KeyboardFocusManager class, as described in Tracking Focus Changes to Multiple Components in How to Use the Focus Subsystem.

The following example demonstrates focus events. The window displays a variety of components. A focus listener, registered on each component, reports every focus-gained and focus-lost event. For each event, the other component involved in the focus change, the opposite component, is reported. For example, when the focus goes from a button to a text field, a focus-lost event is fired by the button (with the text field as the opposite component) and then a focus-gained event is fired by the text field (with the button as the opposite component). Focus-lost as well as focus-gained events can be temporary. For example, a temporary focus-lost event occurs when the window loses the focus. A temporary focus-gained event occurs on popup menus.


Running the Example

  1. Click the Launch button to run FocusEventDemo using Java™ Web Start (download JDK 7 or later). Alternatively, to compile and run the example yourself, consult the example index.
  2. You will see a «Focus gained: JTextField» message in the text area — its «opposite component» is null, since it is the first component to have the focus.
  3. Click the label. Nothing happens because the label, by default, cannot get the focus.
  4. Click the combo box. A focus-lost event is fired by the text field and a focus-gained event by the combo box. The combo box now shows that it has the focus, perhaps with a dotted line around the text — exactly how this is represented is look and feel dependent.
    Notice that when the focus changes from one component to another, the first component fires a focus-lost event before the second component fires a focus-gained event.
  5. Select a choice from the combo box’s menu. Click the combo box again. Notice that no focus event is reported. As long as the user manipulates the same component, the focus stays on that component.
  6. Click the text area where the focus events are printed. Nothing happens because the text area has been rendered unclickable with setRequestFocusEnabled(false) .
  7. Click the text field to return the focus to the initial component.
  8. Press Tab on the keyboard. The focus moves to the combo box and skips over the label.
  9. Press Tab again. The focus moves to the button.
  10. Click another window so that the FocusEventDemo window loses the focus. A temporary focus-lost event is generated for the button.
  11. Click the top of the FocusEventDemo window. A focus-gained event is fired by the button.
  12. Press Tab on the keyboard. The focus moves to the list.
  13. Press Tab again. The focus moves to the text area.
    Notice that even though you are not allowed to click on the text area, you can tab to it. This is so users who use assistive technologies can determine that a component is there and what it contains. The demo disables click-to-focus for the text area, while retaining its tab-to-focus capability, by invoking setRequestFocusEnabled(false) on the text area. The demo could use setFocusable(false) to truly remove the text area from the focus cycle, but that would have the unfortunate effect of making the component unavailable to those who use assistive technologies.
  14. Press Tab again. The focus moves from the list back to the text field. You have just completed a focus cycle. See the introduction in How to Use the Focus Subsystem for a discussion of focus terminology and concepts.
Цукерберг рекомендует:  Марафон - Марафон успехов Основы программирования 5 -15 сентября 2020

The complete code for this demo is in the FocusEventDemo.java file. The following code snippet represents the focus-event handling mechanism:

The Focus Listener API

The corresponding adapter class is FocusAdapter .

Method Purpose
focusGained(FocusEvent) Called just after the listened-to component gets the focus.
focusLost(FocusEvent) Called just after the listened-to component loses the focus.
Method Purpose
boolean isTemporary() Returns the true value if a focus-lost or focus-gained event is temporary.
Component getComponent()
(in java.awt.event.ComponentEvent )
Returns the component that fired the focus event.
Component getOppositeComponent() Returns the other component involved in the focus change. For a FOCUS_GAINED event, this is the component that lost the focus. For a FOCUS_LOST event, this is the component that gained the focus. If the focus change involves a native application, a Java application in a different VM or context, or no other component, then null is returned.

Examples that Use Focus Listeners

The following table lists the examples that use focus listeners.

Принципы обработки событий

Содержание

Введение

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

Модель обработки событий из набора компонентов Swing ассоциирует каждый компонент с его наблюдателем таким образом, чтобы при возникновении события об этом уведомлялись все его наблюдатели. Наблюдатель можно назвать объектом, «заинтересованным» в возникновении события. Узнать о наблюдателях, применяемых для некоторых событий компонента, мы сможем на примере Swing.

При использовании компонентов Swing наблюдателей называют слушателями событий. Они должны реализовывать пустой интерфейс java.util.EventListener, а также (почти во всех случаях) интерфейс слушателя подкласса, который должен иметь хотя бы один метод. События остаются событиями, однако они должны создавать подкласс класса java.util.EventObject. Чрезвычайно важно знать, с какими событиями компонента ассоциированы определенные слушатели событий.

Прежде чем начать изучение принципа поиска событий, ассоциированных с компонентами, рассмотрите частный случай – выбор кнопки JButton. За данное действие отвечает событие ActionEvent, которое генерируется при выборе пользователем кнопки JButton. Если какой-либо объект заинтересован в происхождении данного события, его необходимо зарегистрировать для кнопки JButton.

Для события ActionEvent регистрация проводится по форме ActionListener. Имена в ней связаны соответствующим образом, а для каждого события формы ABCEvent ассоциированным слушателем является ABCListener, где вместо ABC указывается конкретный тип события.

Регистрация происходит при вызове метода addActionListener. Каждый зарегистрированный реализатор уведомляется путем передачи (при генерации события ActionEvent) реализации интерфейса слушателя методу addActionListener. У одного события может быть несколько наблюдателей.

Весь процесс представлен следующими пунктами (хотя порядок их следования может меняться).

Определить для заданного события класс, реализующий связанный с ним интерфейс. В существующее определение класса можно добавить строку «implements ABCListener» или создать новый класс, реализующий данный интерфейс.

Добавления в определение класса строки «implements ABCListener» недостаточно. Кроме этого необходимо реализовать каждый метод данного интерфейса. У одних слушателей (например, ActionListener) есть только один метод. У других (например, WindowListener, используемого при перемещении или закрытии окна) – несколько. Код можно компилировать тогда, когда определены все методы слушателей. Однако и это еще не все. Для того чтобы программа должным образом реагировала на события необходимо выполнить последнее действие.


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

В данной программе продемонстрирован случай обработки события «выбор кнопки»:

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

class MyActionListener implements ActionListener <
public void actionPerformed ( ActionEvent e ) <
System.out.println ( «Thank you.» ) ;
>
>

public class SelectMe extends JFrame <

public SelectMe () <
super ( «Hello» ) ;
setDefaultCloseOperation ( EXIT_ON_CLOSE ) ;
JButton button = new JButton ( «Pick Me» ) ;
ActionListener listener = new MyActionListener () ;
button.addActionListener ( listener ) ;
getContentPane () .add ( button, BorderLayout.CENTER ) ;
setSize ( 200 , 200 ) ;
>

public static void main ( String args []) <
JFrame frame = new SelectMe () ;
frame.show () ;
>
>

Как узнать, какие события инициируются каждым из компонентов? Ответ на этот вопрос можно найти в документации по API. Взгляните еще раз на пару методов add/removeABCListener, в которых вместо ABC указывается тип события. Для каждой пары методов add/remove будет сгенерировано отдельное событие. Для того чтобы отключить отправку уведомления о происхождении события используйте метод removeABCListener.

Рассмотрим класс JButton с целью определения, какие еще события можно «услышать». В документации API по классу JButton сказано, что кнопка может реагировать и на отсутствие события. В данном классе нет методов add/remove. Это один из случаев, когда используются принципы объектно-ориентированного программирования. Необходимо взглянуть в суперкласс AbstractButton. Множество его поведений используется совместно несколькими выбираемыми Swing компонентами, таким образом, базис кода обработки событий переносится на уровень выше.

На уровне AbstractButton слушателями, ассоциируемыми с классом Jbutton, кроме ActionListener могут быть ChangeListener и ItemListener.

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

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

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

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

class MyActionListener implements ActionListener <
public void actionPerformed ( ActionEvent e ) <
System.out.println ( «Thank you.» ) ;
>
>

class MyChangeListener implements ChangeListener <
public void stateChanged ( ChangeEvent e ) <
System.out.println ( «You’re welcome.» ) ;
>
>

public class SelectMe extends JFrame <

public SelectMe () <
super ( «Hello» ) ;
setDefaultCloseOperation ( EXIT_ON_CLOSE ) ;
JButton button = new JButton ( «Pick Me» ) ;
ActionListener aListener = new MyActionListener () ;
button.addActionListener ( aListener ) ;
ChangeListener cListener = new MyChangeListener () ;
button.addChangeListener ( cListener ) ;
getContentPane () .add ( button, BorderLayout.CENTER ) ;
setSize ( 200 , 200 ) ;
>

public static void main ( String args []) <
JFrame frame = new SelectMe () ;
frame.show () ;
>
>

Как уже упоминалось ранее, с классом JButton можно ассоциировать также слушатель ItemListener. Но на этом обработка событий кнопки не заканчивается. Двигаясь дальше, мы столкнемся с суперклассом JComponent для класса AbstractButton.

Для класса JComponent родительским будет класс Container, чьим родительским классом будет, соответственно, класс Component. На каждом из данных уровней иерархии имеется свой набор слушателей, которые можно ассоциировать с кнопкой. У класса java.lang.Object таких слушателей нет.

Далее перечислены все возможные события, которые инициирует класс JButton и которые можно «услышать».

java.awt.Component: ComponentListener, FocusListener, HierarchyBoundsListener, HierarchyListener, InputMethodListener, KeyListener, MouseListener, MouseMotionListener, MouseWheelListener, PropertyChangeListener

java.awt.Container: ContainerListener, PropertyChangeListener javax.swing.JComponent AncestorListener, PropertyChangeListener, VetoableChangeListener

javax.swing.AbstractButton: ActionListener, ChangeListener, ItemListener

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

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

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

Классы Adapter

API AWT и Project Swing определяют интерфейсы, называемые слушателями. У каждого типа события есть интерфейс слушателя, а у каждого слушателя есть методы для каждого возможного события.

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

Например, интерфейс MouseListener сконструирован для того, чтобы получать для компонента события мыши (press, release, click, enter, exit). Для использования интерфейса 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)

Если для вашего приложения требуется переопределить только один из этих методов, то необходимо будет также реализовать и остальные. Избежать реализации методов пустого интерфейса можно путем использования классов adapter.

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

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

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

public class MouseAdapterExample extends JFrame <
JButton button1, button2;
JTextField tf;

public MouseAdapterExample () <
// открыть конструктор

// создать кнопки и добавить слушателей
button1 = new JButton ( «Button 1» ) ;
button1.setName ( «Button 1» ) ;
button1.addMouseListener ( new MouseHandler ()) ;
button2 = new JButton ( «Button 2» ) ;
button2.setName ( «Button 2» ) ;
button2.addMouseListener ( new MouseHandler ()) ;

// Создать текстовое поле, в котором
// пользователь не сможет вводить текст
tf = new JTextField ( 25 ) ;
tf.setEditable ( false ) ;

// создать панели, добавить кнопки и текстовое поле
JPanel p1 = new JPanel () ;
p1.setBackground ( Color.white ) ;
p1.add ( button1 ) ;
p1.add ( button2 ) ;

JPanel p2 = new JPanel () ;
p2.setBackground ( Color.white ) ;
p2.add ( tf ) ;

// получить ContentPane и добавить панели
getContentPane () .setLayout ( new BorderLayout ()) ;
getContentPane () .add ( p1, BorderLayout.NORTH ) ;
getContentPane () .add ( p2, BorderLayout.SOUTH ) ;

addWindowListener ( new WinClosing ()) ;
setBounds ( 100 , 100 , 300 , 100 ) ;
setVisible ( true ) ;

// MouseHandler обрабатывает события мыши и
// расширяет класс adapter, обеспечивающий пустые
// методы. Данный класс (MouseHandler) переопределяет
// методы mouseEntered и mouseExit.
class MouseHandler extends MouseAdapter <
public void mouseEntered ( MouseEvent me )
<
// При перемещении мыши над кнопкой
// имя кнопки фиксируется и отображается в текстовом поле.
tf.setText ( «Mouse is over
» +me.getComponent () .getName ()) ;
>

public void mouseExited ( MouseEvent me ) <
// Когда мышь покидает область кнопки
// значение в текстовом поле сбрасывается.

public static void main ( String args []) <
MouseAdapterExample mae = new MouseAdapterExample () ;
>
>

// Данный класс расширяет класс adapter и
// переопределяет только один метод: windowClosing. Вместо
// того, чтобы использовать данный класс для закрытия окна,
// вы можете добавить в код еще одну строку:
// setDefaultCloseOperation(EXIT_ON_CLOSE);
// как показано ранее в примере SelectMe.
class WinClosing extends WindowAdapter <
public void windowClosing ( WindowEvent we ) <
System.exit ( 0 ) ;
>
>

Цукерберг рекомендует:  Запись - Как посмотреть пропущенный урок в режиме записи

Интерфейс KeyListener и абстрактный класс KeyAdapter

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

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

В качестве примера в следующем приложении создается объект, который устанавливает, вводятся ли с клавиатуры какие-либо символы. Введенный текст отображается в метке внизу экрана:

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

public class KeyAdapterExample extends JFrame <
// Метка, отображающая введенный текст.
JLabel label;
// Окно, в котором перемещается мышь и вводится текст
JPanel p;

public KeyAdapterExample () <
label = new JLabel ( «You typed: » ) ;

p = new JPanel () ;
p.setBackground ( Color.white ) ;
// Зарегистрировать введенный символ
p.addKeyListener ( new KeyHandler ()) ;
// Зарегистрировать перемещение мыши в области глухой панели
p.addMouseListener ( new MyMouseAdapter ( p )) ;

// Получить ContentPane и отформатировать
getContentPane () .setLayout ( new BorderLayout ()) ;
getContentPane () .add ( p, BorderLayout.CENTER ) ;
getContentPane () .add ( label, BorderLayout.SOUTH ) ;
// зарегистрировать выход из программы
addWindowListener ( new WinClosing ()) ;
setBounds ( 100 , 100 , 200 , 200 ) ;
setVisible ( true ) ;
>

// Класс, обрабатывающий набор символов
class KeyHandler extends KeyAdapter <
// Метод, извлекающий набранные символы и
// устанавливающий их в качестве значений метки
public void keyTyped ( KeyEvent ke ) <
label.setText ( «You typed: » + ke.getKeyChar ()) ;
label.invalidate () ;
invalidate () ;
validate () ;
>
>

// Класс, обрабатывающий перемещение мыши
class MyMouseAdapter extends MouseAdapter <
MyMouseAdapter ( Component c ) <
this .c = c;
>

public void mousePressed ( MouseEvent e ) <
c.requestFocus () ;
>

private Component c;
>

public static void main ( String args []) <
KeyAdapterExample kae = new KeyAdapterExample () ;
>
>

Как связать KeyListener с gui в java?

Я хочу сделать змейку на джаве, но у меня проблема с тем, что бы связать кнопки клавиатуры и движение графики. Я уже и так и сяк эти листенеры кручу, у меня в какой-то момент получилось, но почему-то когда я запустил повторно опять ничего не произошло(или это у меня глюки?). В общем надо заставить двигаться квадрат по экрану на WDSA. Помогите пожалуйста.
package com.company;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Snake extends JComponent <
int x = 350;
int y = 350;
public MyPan drawPanel;
JFrame frame;

java KeyListener не работает регулярно [дублировать]


Я пытаюсь что-то сделать, когда одна из клавиш со стрелками нажата с помощью KeyListener в моем классе JPanel. Вот мой код:

Мой основной метод добавляет новый экземпляр этой панели в кадр и отображает его. Нужно ли добавлять ключевой список в JFrame? В моем случае это было бы сложно и неэффективно, поэтому я хотел бы, если возможно, работать с этим JPanel. Кто-нибудь знает, что я делаю неправильно?

EDIT: Код привязки клавиш, который тоже не работает:

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

3 ответа

Если вы ищете эту проблему, вы увидите, что ее спрашивают и ее решают много раз.

  • KeyListeners должны быть на сфокусированном компоненте для работы. Одно из решений заключается в том, чтобы дать вашему компоненту фокус после того, как он сделал его фокусируемым.
  • Лучше использовать длинный снимок — использовать привязки клавиш. Google.

Пожалуйста, посмотрите на мой ответ на этот вопрос для получения дополнительной информации об этом, включая многие детали gory.

Библиотека примеров приложений Java

Оглавление
Коды клавиш

Ввод символов
Аплеты JDK 1.1 и клавиатура
Аплет JDK 1.0 и клавиатура
Мышь в JDK 1.1
Перемещение объектов
Аплет JDK 1.0 и мышь
Регулируем размер изображения
Автономное приложение и мышь

4.1. Просмотр кодов клавиш в приложении JDK 1.1

На примере автономного приложения Java мы покажем вам способ обработки событий от клавиатуры. В своем окне наше приложение показывает код и название каждой нажатой или отжатой клавиши. При этом мы используем механизм обработки событий, принятый в JDK версии 1.1 и более старших версий.

Немного теории

Реализовав интерфейс KeyListener и зарегистрировав приемник событий при помощи метода addKeyListener, приложение Java сможет работать с клавиатурой.

В рамках интерфейса KeyListener ваше приложение должно определить три метода с именами keyPressed, keyReleased и keyTyped. Первые два из них будут получать управление, соответственно, при нажатии и отпускании клавиш. Метод keyTyped вызывается в том случае, если пользователь нажал и отпустил клавишу или комбинацию клавиш (такую, например, как ).

Всем перечисленным выше методам передается ссылка на объект класса KeyEvent, например:

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

Внутри обработчиков 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
VK_BACK_QUOTE Обратная кавычка
VK_BACK_SLASH Обратный слеш
VK_BACK_SPACE Пробел
VK_CANCEL Отмена
VK_CAPS_LOCK
VK_CLEAR Очистка
VK_CLOSE_BRACKET Закрывающая скобка
VK_COMMA Запятая
VK_CONTROL
VK_DECIMAL Десятичная точка
VK_DELETE
VK_DIVIDE Деление
VK_DOWN Перемещение курсора вниз
VK_END
VK_ENTER
VK_EQUALS Равенство
VK_ESCAPE
VK_F1, VK_F2, …, VK_F12 Функциональные клавиши , …,
VK_HELP Запрос подсказки
VK_HOME
VK_INSERT
VK_LEFT Перемещение курсора влево
VK_MULTIPLY Умножение
VK_NUM_LOCK
VK_NUMPAD0, VK_NUMPAD1, …, VK_NUMPAD9 Цифровые клавиши 0, …, 9, расположенные на отдельной цифровой клавиатуре
VK_OPEN_BRACKET Открывающая скобка
VK_PAGE_DOWN
VK_PAGE_UP
VK_PERIOD Точка
VK_PRINTSCREEN
VK_QUOTE Запятая
VK_RIGHT Перемещение курсора вправо
VK_SCROLL_LOCK
VK_SEMICOLON Точка с запятой
VK_SEPARATER Разделитель
VK_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, определенного в нашем приложении:

После создания объекта мы инициализируем его методом init и отображаем методом show.

Класс FrameWindow


Этот класс создан нами на базе класса Frame. Для обработки событий от клавиатуры он реализует интерфейс KeyListener. Дополнительно этот класс также реализует интерфейс WindowListener, что необходимо для правильного завершения работы приложения при удалении его окна:

Поля класса FrameWindow

В классе FrameWindow мы определили всего два поля:

Первое из них с именем yHeight хранит высоту символов текущего шрифта, а второе — размеры окна приложения. Оба поля используются в процессе свертки строк, отображаемых в окне приложения.

Конструктор класса FrameWindow

Этот конструктор достаточно прост:

Он вызывает конструктор базового класса Frame, устанавливает методом setSize размеры окна приложения, а также цвет фона и текста.

Метод init класса FrameWindow

В задачу метода init класса FrameWindow входит регистрация обработчиков событий от клавиатуры и от главного окна приложения:

Регистрация выполняется, соответственно, методами addKeyListener и addWindowListener.

Метод keyPressed класса FrameWindow

Когда пользователь нажимает клавишу, управление передается методу keyPressed, реализованному как часть интерфейса KeyListener:

При помощи метода getKeyCode мы проверяем виртуальный код нажатой клавиши. Если он равен KeyEvent.VK_F3 (то есть соответствует функциональной клавише ), приложение завершает свою работу.

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

Далее метод lineFeed, также определенный в нашем приложении, выполняет свертку содержимого окна, сдвигая старые сообщения на одну строку вниз.

Метод keyReleased класса FrameWindow

Исходный текст этого метода представлен ниже:

Здесь мы, также как и для метода keyPressed, вызываем методы showKeyboardInfo и lineFeed. Однако через второй параметр методу showKeyboardInfo передается значение false — признак того, что клавиша была отжата.

Метод keyTyped класса FrameWindow

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

Метод showKeyboardInfo класса FrameWindow

Прежде всего метод showKeyboardInfo получает ссылку на контекст отображения окна приложения:

Далее в этом контексте устанавливается шрифт с фиксированной шириной символов Courier:

Вслед за этим метод формирует текстовую строку s, записывая в нее виртуальный код клавиши и текстовое описание кода клавиши:

Код символа определяется при помощи метода getKeyCode, а текстовое описание — при помощи метода getKeyText. Заметим, что в качестве параметра методу getKeyText необходимо передать виртуальный код клавиши, например, полученный от метода getKeyCode.

Далее метод проверяет флаг down. Если клавиша была нажата, он равен true, если отжата — false. Мы дописываем к переменной s соответствующую строку и рисуем эту переменную в верхней части окна приложения:

Метод lineFeed класса FrameWindow

В задачу метода lineFeed входит свертка нижней части окна приложения после отображения очередной строки сообщения.

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

Далее метод получает метрики этого шрифта и определяет высоту символов, сохраняя ее в поле yHeight:

В поле wndDimension записываются размеры окна приложения:

Свертка выполняется методом copyArea:

Здесь мы сдвигаем верхнюю часть окна приложения вниз на размер символов шрифта Courier.

Далее верхняя часть окна, где отображаются новые сообщения, закрашивается желтым цветом:

Метод paint класса FrameWindow


Этот метод просто вызывает метод paint из родительского класса Frame:

Метод windowClosing класса FrameWindow

Метод windowClosing реализован нами как часть интерфейса WindowListener:

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

Другие методы интерфейса WindowListener

Мы также реализовали и другие методы интерфейса WindowListener:

Наши реализации ничего не делают, однако определения этих методов необходимы для полноты интерфейса WindowListener.

Принципы обработки событий

Содержание

Введение

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

Модель обработки событий из набора компонентов Swing ассоциирует каждый компонент с его наблюдателем таким образом, чтобы при возникновении события об этом уведомлялись все его наблюдатели. Наблюдатель можно назвать объектом, «заинтересованным» в возникновении события. Узнать о наблюдателях, применяемых для некоторых событий компонента, мы сможем на примере Swing.

При использовании компонентов Swing наблюдателей называют слушателями событий. Они должны реализовывать пустой интерфейс java.util.EventListener, а также (почти во всех случаях) интерфейс слушателя подкласса, который должен иметь хотя бы один метод. События остаются событиями, однако они должны создавать подкласс класса java.util.EventObject. Чрезвычайно важно знать, с какими событиями компонента ассоциированы определенные слушатели событий.

Прежде чем начать изучение принципа поиска событий, ассоциированных с компонентами, рассмотрите частный случай – выбор кнопки JButton. За данное действие отвечает событие ActionEvent, которое генерируется при выборе пользователем кнопки JButton. Если какой-либо объект заинтересован в происхождении данного события, его необходимо зарегистрировать для кнопки JButton.

Для события ActionEvent регистрация проводится по форме ActionListener. Имена в ней связаны соответствующим образом, а для каждого события формы ABCEvent ассоциированным слушателем является ABCListener, где вместо ABC указывается конкретный тип события.

Регистрация происходит при вызове метода addActionListener. Каждый зарегистрированный реализатор уведомляется путем передачи (при генерации события ActionEvent) реализации интерфейса слушателя методу addActionListener. У одного события может быть несколько наблюдателей.

Весь процесс представлен следующими пунктами (хотя порядок их следования может меняться).

Определить для заданного события класс, реализующий связанный с ним интерфейс. В существующее определение класса можно добавить строку «implements ABCListener» или создать новый класс, реализующий данный интерфейс.

Добавления в определение класса строки «implements ABCListener» недостаточно. Кроме этого необходимо реализовать каждый метод данного интерфейса. У одних слушателей (например, ActionListener) есть только один метод. У других (например, WindowListener, используемого при перемещении или закрытии окна) – несколько. Код можно компилировать тогда, когда определены все методы слушателей. Однако и это еще не все. Для того чтобы программа должным образом реагировала на события необходимо выполнить последнее действие.

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

В данной программе продемонстрирован случай обработки события «выбор кнопки»:

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

class MyActionListener implements ActionListener <
public void actionPerformed ( ActionEvent e ) <
System.out.println ( «Thank you.» ) ;
>
>

public class SelectMe extends JFrame <

public SelectMe () <
super ( «Hello» ) ;
setDefaultCloseOperation ( EXIT_ON_CLOSE ) ;
JButton button = new JButton ( «Pick Me» ) ;
ActionListener listener = new MyActionListener () ;
button.addActionListener ( listener ) ;
getContentPane () .add ( button, BorderLayout.CENTER ) ;
setSize ( 200 , 200 ) ;
>

public static void main ( String args []) <
JFrame frame = new SelectMe () ;
frame.show () ;
>
>

Как узнать, какие события инициируются каждым из компонентов? Ответ на этот вопрос можно найти в документации по API. Взгляните еще раз на пару методов add/removeABCListener, в которых вместо ABC указывается тип события. Для каждой пары методов add/remove будет сгенерировано отдельное событие. Для того чтобы отключить отправку уведомления о происхождении события используйте метод removeABCListener.

Рассмотрим класс JButton с целью определения, какие еще события можно «услышать». В документации API по классу JButton сказано, что кнопка может реагировать и на отсутствие события. В данном классе нет методов add/remove. Это один из случаев, когда используются принципы объектно-ориентированного программирования. Необходимо взглянуть в суперкласс AbstractButton. Множество его поведений используется совместно несколькими выбираемыми Swing компонентами, таким образом, базис кода обработки событий переносится на уровень выше.

На уровне AbstractButton слушателями, ассоциируемыми с классом Jbutton, кроме ActionListener могут быть ChangeListener и ItemListener.

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

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

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

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

class MyActionListener implements ActionListener <
public void actionPerformed ( ActionEvent e ) <
System.out.println ( «Thank you.» ) ;
>
>

class MyChangeListener implements ChangeListener <
public void stateChanged ( ChangeEvent e ) <
System.out.println ( «You’re welcome.» ) ;
>
>

public class SelectMe extends JFrame <


public SelectMe () <
super ( «Hello» ) ;
setDefaultCloseOperation ( EXIT_ON_CLOSE ) ;
JButton button = new JButton ( «Pick Me» ) ;
ActionListener aListener = new MyActionListener () ;
button.addActionListener ( aListener ) ;
ChangeListener cListener = new MyChangeListener () ;
button.addChangeListener ( cListener ) ;
getContentPane () .add ( button, BorderLayout.CENTER ) ;
setSize ( 200 , 200 ) ;
>

public static void main ( String args []) <
JFrame frame = new SelectMe () ;
frame.show () ;
>
>

Как уже упоминалось ранее, с классом JButton можно ассоциировать также слушатель ItemListener. Но на этом обработка событий кнопки не заканчивается. Двигаясь дальше, мы столкнемся с суперклассом JComponent для класса AbstractButton.

Для класса JComponent родительским будет класс Container, чьим родительским классом будет, соответственно, класс Component. На каждом из данных уровней иерархии имеется свой набор слушателей, которые можно ассоциировать с кнопкой. У класса java.lang.Object таких слушателей нет.

Далее перечислены все возможные события, которые инициирует класс JButton и которые можно «услышать».

java.awt.Component: ComponentListener, FocusListener, HierarchyBoundsListener, HierarchyListener, InputMethodListener, KeyListener, MouseListener, MouseMotionListener, MouseWheelListener, PropertyChangeListener

java.awt.Container: ContainerListener, PropertyChangeListener javax.swing.JComponent AncestorListener, PropertyChangeListener, VetoableChangeListener

javax.swing.AbstractButton: ActionListener, ChangeListener, ItemListener

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

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

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

Классы Adapter

API AWT и Project Swing определяют интерфейсы, называемые слушателями. У каждого типа события есть интерфейс слушателя, а у каждого слушателя есть методы для каждого возможного события.

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

Например, интерфейс MouseListener сконструирован для того, чтобы получать для компонента события мыши (press, release, click, enter, exit). Для использования интерфейса 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)

Если для вашего приложения требуется переопределить только один из этих методов, то необходимо будет также реализовать и остальные. Избежать реализации методов пустого интерфейса можно путем использования классов adapter.

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

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

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

public class MouseAdapterExample extends JFrame <
JButton button1, button2;
JTextField tf;

public MouseAdapterExample () <
// открыть конструктор

// создать кнопки и добавить слушателей
button1 = new JButton ( «Button 1» ) ;
button1.setName ( «Button 1» ) ;
button1.addMouseListener ( new MouseHandler ()) ;
button2 = new JButton ( «Button 2» ) ;
button2.setName ( «Button 2» ) ;
button2.addMouseListener ( new MouseHandler ()) ;

// Создать текстовое поле, в котором
// пользователь не сможет вводить текст
tf = new JTextField ( 25 ) ;
tf.setEditable ( false ) ;

// создать панели, добавить кнопки и текстовое поле
JPanel p1 = new JPanel () ;
p1.setBackground ( Color.white ) ;
p1.add ( button1 ) ;
p1.add ( button2 ) ;

JPanel p2 = new JPanel () ;
p2.setBackground ( Color.white ) ;
p2.add ( tf ) ;

// получить ContentPane и добавить панели
getContentPane () .setLayout ( new BorderLayout ()) ;
getContentPane () .add ( p1, BorderLayout.NORTH ) ;
getContentPane () .add ( p2, BorderLayout.SOUTH ) ;

addWindowListener ( new WinClosing ()) ;
setBounds ( 100 , 100 , 300 , 100 ) ;
setVisible ( true ) ;

// MouseHandler обрабатывает события мыши и
// расширяет класс adapter, обеспечивающий пустые
// методы. Данный класс (MouseHandler) переопределяет
// методы mouseEntered и mouseExit.
class MouseHandler extends MouseAdapter <
public void mouseEntered ( MouseEvent me )
<
// При перемещении мыши над кнопкой
// имя кнопки фиксируется и отображается в текстовом поле.
tf.setText ( «Mouse is over
» +me.getComponent () .getName ()) ;
>

public void mouseExited ( MouseEvent me ) <
// Когда мышь покидает область кнопки
// значение в текстовом поле сбрасывается.

public static void main ( String args []) <
MouseAdapterExample mae = new MouseAdapterExample () ;
>
>


// Данный класс расширяет класс adapter и
// переопределяет только один метод: windowClosing. Вместо
// того, чтобы использовать данный класс для закрытия окна,
// вы можете добавить в код еще одну строку:
// setDefaultCloseOperation(EXIT_ON_CLOSE);
// как показано ранее в примере SelectMe.
class WinClosing extends WindowAdapter <
public void windowClosing ( WindowEvent we ) <
System.exit ( 0 ) ;
>
>

Интерфейс KeyListener и абстрактный класс KeyAdapter

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

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

В качестве примера в следующем приложении создается объект, который устанавливает, вводятся ли с клавиатуры какие-либо символы. Введенный текст отображается в метке внизу экрана:

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

public class KeyAdapterExample extends JFrame <
// Метка, отображающая введенный текст.
JLabel label;
// Окно, в котором перемещается мышь и вводится текст
JPanel p;

public KeyAdapterExample () <
label = new JLabel ( «You typed: » ) ;

p = new JPanel () ;
p.setBackground ( Color.white ) ;
// Зарегистрировать введенный символ
p.addKeyListener ( new KeyHandler ()) ;
// Зарегистрировать перемещение мыши в области глухой панели
p.addMouseListener ( new MyMouseAdapter ( p )) ;

// Получить ContentPane и отформатировать
getContentPane () .setLayout ( new BorderLayout ()) ;
getContentPane () .add ( p, BorderLayout.CENTER ) ;
getContentPane () .add ( label, BorderLayout.SOUTH ) ;
// зарегистрировать выход из программы
addWindowListener ( new WinClosing ()) ;
setBounds ( 100 , 100 , 200 , 200 ) ;
setVisible ( true ) ;
>

// Класс, обрабатывающий набор символов
class KeyHandler extends KeyAdapter <
// Метод, извлекающий набранные символы и
// устанавливающий их в качестве значений метки
public void keyTyped ( KeyEvent ke ) <
label.setText ( «You typed: » + ke.getKeyChar ()) ;
label.invalidate () ;
invalidate () ;
validate () ;
>
>

// Класс, обрабатывающий перемещение мыши
class MyMouseAdapter extends MouseAdapter <
MyMouseAdapter ( Component c ) <
this .c = c;
>

public void mousePressed ( MouseEvent e ) <
c.requestFocus () ;
>

private Component c;
>

public static void main ( String args []) <
KeyAdapterExample kae = new KeyAdapterExample () ;
>
>

Java — Java выбор фокуса для KeyListener

import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class MoveTest extends JFrame implements KeyListener<

private JTextField textField = new JTextField(20);

private JTextField textField1 = new JTextField(20);

private JLabel label= new JLabel(«hello»);

public MoveTest() <
setLayout(null);
initialize();
>

private void initialize() <
textField.setSize(50,50);
textField.setLocation(100,100);
textField.addKeyListener(this);

textField1.setSize(50,50);
textField1.setLocation(200,100);
textField1.addKeyListener(this);

label.setSize(50,50);
label.setLocation(300,100);
label.addKeyListener(this);

getContentPane().add(textField);
getContentPane().add(textField1);
getContentPane().add(label);
setSize(640, 480);
show();
>

public static void main(String[] args) <
new MoveTest();
>

public void keyTyped(KeyEvent arg0) <
// TODO Auto-generated method stub

public void keyPressed(KeyEvent arg0) <
Point point = arg0.getComponent().getLocation();
if(arg0.getKeyCode()== 37) <
point.x -= 1;
>else if(arg0.getKeyCode()== 38) <
point.y -=1;
>else if(arg0.getKeyCode()== 39) <
point.x +=1;
>else if(arg0.getKeyCode()== 40) <
point.y +=1;
>

arg0.getComponent().setLocation(point);
validate();
repaint();
>

public void keyReleased(KeyEvent arg0) <
// TODO Auto-generated method stub

проблема

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

JFrameList list = new JFrameList (); addKeyListener (список); // использовать переменную списка для доступа к коду keyPressed

Конечно, это не то поведение, которое вы хотите. Вы хотите, чтобы нажатия клавиш были сохранены в текущем экземпляре, а не в новом объекте. Это означает, что вы должны делать

Хотя вы можете заметить, что слушатель работает только «иногда», а может и вовсе не в зависимости от того, как вы его тестируете.

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

Решение

Если вы решите продолжать использовать слушателя, вы должны добавить его к своим кнопкам, а не к фрейму:

Вместо того, чтобы проверять код клавиши события, вы можете получить источник события (вашу кнопку), позвонив event.getSource() .

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

Вы JFrameList должны теперь реализовать, ActionListener а не KeyListener , так как он будет получать ваши события как действия:

альтернатива

JButton имеет встроенную мнемоническую обработку. Вы можете указать мнемонику через JButton#setMnemonic(int) , где аргумент является кодом ключа:

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

плюса

282232 Репутация автора

Ключевые события отправляются только компоненту с фокусом. Вы не опубликовали весь код, но я предполагаю, что фокус находится на кнопке, которую вы добавляете в фрейм, поэтому кнопка получает KeyEvent.

Не уверен, что вы пытаетесь сделать с KeyListener. Вы не можете определить, какая кнопка была нажата, посмотрев на символ, напечатанный в KeyEvent.

Если вы хотите знать, какая кнопка нажата, вам нужно добавить ActionListener к каждой кнопке. Прочитайте раздел руководства Swing по использованию кнопок для получения дополнительной информации и примеров.

Цукерберг рекомендует:  Ооп - Java Уровень 2
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих