Pregunta KeyListener no responde para JFrame


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 aparece un mensaje en mi consola. Sin embargo, cuando presiono una tecla, no obtengo ninguno de los otros mensajes, como si KeyListener ni siquiera estaba allí.

Estaba pensando que podría ser porque el foco no está en el JFrame
y entonces ellos KeyListener no recibe ningún evento Pero, estoy bastante seguro de que es así.

¿Hay algo que me falta?


75
2017-11-13 10:17


origen


Respuestas:


Debe agregar su KeyListener a cada componente que necesita. Solo el componente con el foco enviará estos eventos. Por ejemplo, si tiene solo un TextBox en su JFrame, ese TextBox tiene el foco. Por lo tanto, debe agregar KeyListener a este componente también.

El proceso es el mismo:

myComponent.addKeyListener(new KeyListener ...);

Nota: Algunos componentes no son enfocables como JLabel.

Para configurarlos para enfocarse necesitas:

myComponent.setFocusable(true);

46
2017-11-13 13:01



Si no desea registrar un oyente en cada componente,
tú podrías agrega tu propio KeyEventDispatcher al 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);
    }
}

125
2017-09-04 14:09



InputMaps y ActionMaps fueron diseñados para capturar los eventos clave para el componente, él y todos sus subcomponentes, o toda la ventana. Esto se controla a través del parámetro en JComponent.getInputMap (). Ver Cómo usar enlaces de teclas para la documentación.

La belleza de este diseño es que uno puede escoger y elegir qué trazos de tecla son importantes para monitorear y tener diferentes acciones disparadas basadas en esas teclas.

Este código invocará a disponer () en un JFrame cuando se toca 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 clave. El panel de contenido puede ser un componente de este tipo.

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

15
2018-02-23 00:29



KeyListener es de bajo nivel y se aplica solo a un solo componente. A pesar de los intentos de hacerlo más útil JFrame crea una serie de componentes, el más obvio es el panel de contenido. JComboBox La IU también se implementa a menudo de manera similar.

Vale la pena señalar que los eventos del mouse funcionan de una forma extraña y ligeramente diferente de los eventos clave.

Para detalles sobre lo que debe hacer, vea mi respuesta en Acceso directo de teclado de aplicación - Java Swing.


10
2017-11-13 13:18



Tengo el mismo problema hasta que leí que el problema real es acerca de ENFOQUE: su JFrame ya ha agregado Oyentes, pero el marco de recorrido nunca está en el Enfoque porque tiene muchos componentes dentro de su Marco J que también son enfocables, así que intente:

JFrame.setFocusable(true);

Buena suerte


10
2018-04-27 15:30



Deion (y cualquier otra persona que haga una pregunta similar), puede usar el código de Peter anterior, pero en lugar de imprimir a la salida estándar, prueba el código de tecla PRESIONADO, LIBERADO o TIPIFICADO.

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

8
2018-01-09 14:50



para capturar eventos clave de TODOS los campos de texto en una JFrame, uno puede emplear un post procesador de eventos clave. Aquí hay un ejemplo de trabajo, después de agregar lo obvio incluye.

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

4
2017-07-15 19:47



Hmm ... ¿para qué clase es tu constructor? ¿Probablemente alguna clase que extienda JFrame? El foco de la ventana debe estar en la ventana, por supuesto, pero no creo que ese sea el problema.

Expandí tu código, traté de ejecutarlo y funcionó: las pulsaciones de teclas se obtuvieron como resultado 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);
    }
}

3
2017-11-13 10:39



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

3
2018-06-27 15:20



He estado teniendo el mismo problema. Seguí el consejo de Bruno y descubrí que agregar un KeyListener solo al "primer" botón en el JFrame (es decir, en la esquina superior izquierda) hacía el truco. Pero estoy de acuerdo con usted, es una solución algo inquietante. Así que jugueteé y descubrí una manera más ordenada de arreglarlo. Solo agregue la línea

myChildOfJFrame.requestFocusInWindow();

a su método principal, después de haber creado su instancia de su subclase de JFrame y establecerlo visible.


2
2018-01-04 02:31



jaja ... todo lo que tienes que hacer es asegurarte de que

addKeyListener (esto);

está colocado correctamente en tu código.


-1
2017-07-10 19:24