KeyListener sem resposta para JFrame

Estou tentando implementar um KeyListener para o meu JFrame . No construtor, estou usando este código:

 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"); } }); 

Quando eu o executo, a mensagem de test aparece no meu console. No entanto, quando pressiono uma tecla, não recebo nenhuma das outras mensagens, como se o KeyListener nem estivesse lá.

Eu estava pensando que poderia ser porque o foco não está no JFrame
e então eles KeyListener não recebe nenhum evento. Mas tenho certeza que sim.

Há algo que estou sentindo falta?

Você deve adicionar seu keyListener a todos os componentes necessários. Apenas o componente com o foco enviará esses events. Por exemplo, se você tiver apenas um TextBox no seu JFrame, esse TextBox tem o foco. Então você deve adicionar um KeyListener para este componente também.

O processo é o mesmo:

 myComponent.addKeyListener(new KeyListener ...); 

Nota: Alguns componentes não são focalizáveis ​​como o JLabel.

Para colocá-los em foco, você precisa:

 myComponent.setFocusable(true); 

Se você não quiser registrar um ouvinte em todos os componentes,
você poderia adicionar seu próprio KeyEventDispatcher ao 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 e ActionMaps foram projetados para capturar os principais events para o componente, ele e todos os seus subcomponentes, ou a janela inteira. Isto é controlado através do parâmetro em JComponent.getInputMap (). Veja Como usar chaves de binding para documentação.

A beleza desse design é que é possível escolher quais os principais toques que são importantes para monitorar e executar ações diferentes com base nesses toques de tecla.

Este código irá chamar dispose () em um JFrame quando a chave de escape for atingida em qualquer lugar da janela. O JFrame não deriva do JComponent, portanto, você precisa usar outro componente no JFrame para criar a binding de chave. O painel de conteúdo pode ser um desses componentes.

 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 é de baixo nível e aplica-se apenas a um único componente. Apesar das tentativas de torná-lo mais utilizável, o JFrame cria vários componentes, sendo o mais óbvio o painel de conteúdo. JComboBox UI também é frequentemente implementado de maneira similar.

Vale a pena notar que os events do mouse funcionam de maneira estranha e ligeiramente diferente dos principais events.

Para detalhes sobre o que você deve fazer, veja minha resposta no atalho de teclado em todo o aplicativo – Java Swing .

Eu tenho o mesmo problema até que eu li que o problema real é sobre FOCUS o seu JFrame já adicionou Listeners mas o frame da turnê nunca está no Focus porque você tem muitos componentes dentro do seu JFrame que também são focáveis ​​então tente:

 JFrame.setFocusable(true); 

Boa sorte

Deion (e qualquer outra pessoa que faça uma pergunta semelhante), você pode usar o código de Peter acima, mas em vez de imprimir na saída padrão, você testa o código-chave PRESSIONADO, LIBERADO ou TIPO.

 @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; } 

Para capturar os principais events de TODOS os campos de texto em um JFrame , pode-se empregar um pós-processador de evento-chave. Aqui está um exemplo de trabalho, depois de adicionar os includes óbvios.

 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; } } 

Hmm .. para que class é seu construtor? Provavelmente alguma class estendendo JFrame? O foco da janela deve estar na janela, é claro, mas não acho que seja esse o problema.

Eu expandi seu código, tentei executá-lo e funcionou – as teclas pressionadas resultaram como saída de impressão. (execute com o Ubuntu através do 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); } } 

Isso deve ajudar

  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"); } }); 

Eu tenho tido o mesmo problema. Segui o conselho de Bruno para você e descobri que adicionar um KeyListener apenas ao botão “primeiro” no JFrame (ou seja, no canto superior esquerdo) fazia o truque. Mas eu concordo com você, é meio que uma solução inquietante. Então eu brinquei e descobri uma maneira mais simples de consertá-lo. Basta adicionar a linha

 myChildOfJFrame.requestFocusInWindow(); 

ao seu método principal, depois de ter criado sua instância de sua subclass de JFrame e defini-la como visível.

lol …. tudo que você precisa fazer é ter certeza de que

addKeyListener (isso);

é colocado corretamente no seu código.

Você poderia ter JComponents customizados configurando seu JFrame pai como focável.

Basta adicionar um construtor e passar o JFrame. Em seguida, faça uma chamada para setFocusable () em paintComponent.

Desta forma, o JFrame sempre receberá KeyEvents, independentemente de outros componentes serem pressionados.