Estoy tratando de implementar un KeyListener
para mi JFrame
. En el constructor, estoy 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"); }
});
Cuando lo ejecuto, el test
mensaje aparece en mi consola. Sin embargo, cuando presiono una tecla, no recibo ninguno de los otros mensajes, como si KeyListener
ni siquiera estuviera allí.
Estaba pensando que podría ser porque el foco no está en el JFrame
y por eso KeyListener
no reciben ningún evento. Pero estoy bastante seguro de que lo es.
¿Hay algo que me estoy perdiendo?
fuente
Si no desea registrar un oyente en cada componente,
puede agregar el suyo
KeyEventDispatcher
aKeyboardFocusManager
: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); } }
fuente
InputMaps y ActionMaps se diseñaron para capturar los eventos clave para el componente, él y todos sus subcomponentes, o la ventana completa. Esto se controla a través del parámetro en JComponent.getInputMap (). Consulte Cómo utilizar las combinaciones de teclas para obtener documentación.
La belleza de este diseño es que uno puede elegir qué pulsaciones de tecla son importantes para monitorear y hacer que se activen diferentes acciones basadas en esas pulsaciones de tecla.
Este código llamará a dispose () en un JFrame cuando se presione la tecla de escape en cualquier lugar de la ventana. JFrame no se deriva de JComponent, por lo que debe usar otro componente en JFrame para crear el enlace de teclas. El panel de contenido podría ser uno de estos 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);
fuente
KeyListener
es de bajo nivel y se aplica solo a un componente. A pesar de los intentos de hacerlo más utilizable, seJFrame
crean varios componentes, el más obvio es el panel de contenido.JComboBox
La interfaz de usuario también se implementa a menudo de manera similar.Vale la pena señalar que los eventos del mouse funcionan de una manera extraña, ligeramente diferente a los eventos clave.
Para obtener detalles sobre lo que debe hacer, consulte mi respuesta sobre el método abreviado de teclado para toda la aplicación: Java Swing .
fuente
Tuve el mismo problema hasta que leí que el problema real es acerca de FOCUS, su JFrame ya ha agregado oyentes, pero el marco del recorrido nunca está en Focus porque tiene muchos componentes dentro de su JFrame que también se pueden enfocar, así que intente:
JFrame.setFocusable(true);
Buena suerte
fuente
Deion (y cualquier otra persona que haga una pregunta similar), puede usar el código de Peter anterior, pero en lugar de imprimir en la salida estándar, prueba el código de tecla PRESSED, RELEASED o 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; }
fuente
Para capturar eventos clave de TODOS los campos de texto en un JFrame , se puede emplear un postprocesador de eventos clave. Aquí hay un ejemplo práctico, después de agregar las inclusiones obvias.
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; } }
fuente
Hmm ... ¿para qué clase es tu constructor? ¿Probablemente alguna clase que extienda JFrame? El foco de la ventana debería estar en la ventana, por supuesto, pero no creo que ese sea el problema.
Expandí su código, intenté ejecutarlo y funcionó: las pulsaciones de teclas resultaron como salida de impresión. (ejecutar con Ubuntu a través de 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); } }
fuente
Esto debería ayudar
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"); } });
fuente
Yo he tenido el mismo problema. Seguí el consejo de Bruno y descubrí que agregar un KeyListener solo al botón "primero" en el JFrame (es decir, en la parte superior izquierda) funcionó. Pero estoy de acuerdo con usted en que es una solución inquietante. Así que jugueteé y descubrí una forma más ordenada de solucionarlo. Solo agrega la línea
a su método principal, después de haber creado su instancia de su subclase de JFrame y configurarla como visible.
fuente
lol ... todo lo que tienes que hacer es asegurarte de que
addKeyListener (esto);
se coloca correctamente en su código.
fuente
Puede hacer que JComponents personalizados establezcan su JFrame principal enfocable.
Simplemente agregue un constructor y pase el JFrame. Luego haga una llamada a setFocusable () en paintComponent.
De esta manera, el JFrame siempre recibirá KeyEvents independientemente de si se presionan otros componentes.
fuente