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

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

 System.out.println("test"); addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { System.out.println( "tester"); } public void keyReleased(KeyEvent e) { System.out.println("2test2"); } public void keyTyped(KeyEvent e) { System.out.println("3test3"); } }); 

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

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

Есть что-то, чего я не хватает?

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

Процесс тот же:

 myComponent.addKeyListener(new KeyListener ...); 

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

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

 myComponent.setFocusable(true); 

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

 public class MyFrame extends JFrame { private class MyDispatcher implements KeyEventDispatcher { @Override public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED) { System.out.println("tester"); } else if (e.getID() == KeyEvent.KEY_RELEASED) { System.out.println("2test2"); } else if (e.getID() == KeyEvent.KEY_TYPED) { System.out.println("3test3"); } return false; } } public MyFrame() { add(new JTextField()); System.out.println("test"); KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); manager.addKeyEventDispatcher(new MyDispatcher()); } public static void main(String[] args) { MyFrame f = new MyFrame(); f.pack(); f.setVisible(true); } } 

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

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

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

 InputMap inputMap; ActionMap actionMap; AbstractAction action; JComponent component; inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); actionMap = component.getActionMap(); action = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { dispose(); } }; inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose"); actionMap.put("dispose", action); 

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

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

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

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

 JFrame.setFocusable(true); 

Удачи

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

 @Override public boolean dispatchKeyEvent(KeyEvent e) { if (e.getID() == KeyEvent.KEY_PRESSED) { if (e.getKeyCode() == KeyEvent.VK_F4) { dispose(); } } else if (e.getID() == KeyEvent.KEY_RELEASED) { if (e.getKeyCode() == KeyEvent.VK_F4) { dispose(); } } else if (e.getID() == KeyEvent.KEY_TYPED) { if (e.getKeyCode() == KeyEvent.VK_F4) { dispose(); } } return false; } 

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

 public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor { public static final long serialVersionUID = 1L; public KeyListenerF1Demo() { setTitle(getClass().getName()); // Define two labels and two text fields all in a row. setLayout(new FlowLayout()); JLabel label1 = new JLabel("Text1"); label1.setName("Label1"); add(label1); JTextField text1 = new JTextField(10); text1.setName("Text1"); add(text1); JLabel label2 = new JLabel("Text2"); label2.setName("Label2"); add(label2); JTextField text2 = new JTextField(10); text2.setName("Text2"); add(text2); // Register a key event post processor. KeyboardFocusManager.getCurrentKeyboardFocusManager() .addKeyEventPostProcessor(this); } public static void main(String[] args) { JFrame f = new KeyListenerF1Demo(); f.setName("MyFrame"); f.pack(); f.setVisible(true); } @Override public boolean postProcessKeyEvent(KeyEvent ke) { // Check for function key F1 pressed. if (ke.getID() == KeyEvent.KEY_PRESSED && ke.getKeyCode() == KeyEvent.VK_F1) { // Get top level ancestor of focused element. Component c = ke.getComponent(); while (null != c.getParent()) c = c.getParent(); // Output some help. System.out.println("Help for " + c.getName() + "." + ke.getComponent().getName()); // Tell keyboard focus manager that event has been fully handled. return true; } // Let keyboard focus manager handle the event further. return false; } } 

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

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

 public class MyFrame extends JFrame { public MyFrame() { System.out.println("test"); addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { System.out.println("tester"); } public void keyReleased(KeyEvent e) { System.out.println("2test2"); } public void keyTyped(KeyEvent e) { System.out.println("3test3"); } }); } public static void main(String[] args) { MyFrame f = new MyFrame(); f.pack(); f.setVisible(true); } } 

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

  yourJFrame.setFocusable(true); yourJFrame.addKeyListener(new java.awt.event.KeyAdapter() { @Override public void keyTyped(KeyEvent e) { System.out.println("you typed a key"); } @Override public void keyPressed(KeyEvent e) { System.out.println("you pressed a key"); } @Override public void keyReleased(KeyEvent e) { System.out.println("you released a key"); } }); 

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

 myChildOfJFrame.requestFocusInWindow(); 

к вашему основному методу, после того, как вы создали свой экземпляр вашего подclassа JFrame и установите его видимым.

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

addKeyListener (это);

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

Вы могли бы настроить пользовательские JComponents на свой родительский JFrame.

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

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

  • Как отлаживать макеты Java Swing
  • Java GIF анимация не перерисовывается правильно
  • Javafx: Разница между javafx.concurent и Platform.runLater?
  • Java: сохранение формата изображения JPanel
  • Имея изображения в качестве фона JPanel
  • Java Swing: как я могу реализовать экран входа в систему, прежде чем показывать JFrame?
  • Растянуть текст JLabel
  • TableCellRenderer и как обновить фон Cell без использования JTable.repaint ()
  • Как совместить прослушиватели событий с запросом на событие?
  • Java: JProgressBar (или эквивалент) в заголовке вкладки JTabbedPane
  • Загрузка и отображение больших текстовых файлов
  • Давайте будем гением компьютера.