[java] Unresponsive KeyListener for JFrame

I'm trying to implement a KeyListener for my JFrame. On the constructor, I'm using this code:

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

When I run it, the test message comes up in my console. However, when I press a key, I don't get any of the other messages, as if the KeyListener was not even there.

I was thinking that it could be because the focus is not on the JFrame
and so they KeyListener doesn't receive any events. But, I'm pretty sure it is.

Is there something that I am missing?

This question is related to java swing jframe keylistener

The answer is


You must add your keyListener to every component that you need. Only the component with the focus will send these events. For instance, if you have only one TextBox in your JFrame, that TextBox has the focus. So you must add a KeyListener to this component as well.

The process is the same:

myComponent.addKeyListener(new KeyListener ...);

Note: Some components aren't focusable like JLabel.

For setting them to focusable you need to:

myComponent.setFocusable(true);

InputMaps and ActionMaps were designed to capture the key events for the component, it and all of its sub-components, or the entire window. This is controlled through the parameter in JComponent.getInputMap(). See How to Use Key Bindings for documentation.

The beauty of this design is that one can pick and choose which key strokes are important to monitor and have different actions fired based on those key strokes.

This code will call dispose() on a JFrame when the escape key is hit anywhere in the window. JFrame doesn't derive from JComponent so you have to use another component in the JFrame to create the key binding. The content pane might be such a component.

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

You could have custom JComponents set their parent JFrame focusable.

Just add a constructor and pass in the JFrame. Then make a call to setFocusable() in paintComponent.

This way the JFrame will always receive KeyEvents regardless of whether other components are pressed.


lol .... all you have to do is make sure that

addKeyListener(this);

is placed correctly in your code.


KeyListener is low level and applies only to a single component. Despite attempts to make it more usable JFrame creates a number of component components, the most obvious being the content pane. JComboBox UI is also often implemented in a similar manner.

It's worth noting the mouse events work in a strange way slightly different to key events.

For details on what you should do, see my answer on Application wide keyboard shortcut - Java Swing.


You could have custom JComponents set their parent JFrame focusable.

Just add a constructor and pass in the JFrame. Then make a call to setFocusable() in paintComponent.

This way the JFrame will always receive KeyEvents regardless of whether other components are pressed.


lol .... all you have to do is make sure that

addKeyListener(this);

is placed correctly in your code.


Deion (and anyone else asking a similar question), you could use Peter's code above but instead of printing to standard output, you test for the key code PRESSED, RELEASED, or 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;
}

KeyListener is low level and applies only to a single component. Despite attempts to make it more usable JFrame creates a number of component components, the most obvious being the content pane. JComboBox UI is also often implemented in a similar manner.

It's worth noting the mouse events work in a strange way slightly different to key events.

For details on what you should do, see my answer on Application wide keyboard shortcut - Java Swing.


Hmm.. what class is your constructor for? Probably some class extending JFrame? The window focus should be at the window, of course but I don't think that's the problem.

I expanded your code, tried to run it and it worked - the key presses resulted as print output. (run with Ubuntu through 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);
    }
}

InputMaps and ActionMaps were designed to capture the key events for the component, it and all of its sub-components, or the entire window. This is controlled through the parameter in JComponent.getInputMap(). See How to Use Key Bindings for documentation.

The beauty of this design is that one can pick and choose which key strokes are important to monitor and have different actions fired based on those key strokes.

This code will call dispose() on a JFrame when the escape key is hit anywhere in the window. JFrame doesn't derive from JComponent so you have to use another component in the JFrame to create the key binding. The content pane might be such a component.

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

This should help

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

I have been having the same problem. I followed Bruno's advice to you and found that adding a KeyListener just to the "first" button in the JFrame (ie, on the top left) did the trick. But I agree with you it is kind of an unsettling solution. So I fiddled around and discovered a neater way to fix it. Just add the line

myChildOfJFrame.requestFocusInWindow();

to your main method, after you've created your instance of your subclass of JFrame and set it visible.


KeyListener is low level and applies only to a single component. Despite attempts to make it more usable JFrame creates a number of component components, the most obvious being the content pane. JComboBox UI is also often implemented in a similar manner.

It's worth noting the mouse events work in a strange way slightly different to key events.

For details on what you should do, see my answer on Application wide keyboard shortcut - Java Swing.


I got the same problem until i read that the real problem is about FOCUS the your JFrame has already added Listeners but tour frame is never on Focus because you got a lot of components inside your JFrame that also are focusable so try:

JFrame.setFocusable(true);

Good Luck


I have been having the same problem. I followed Bruno's advice to you and found that adding a KeyListener just to the "first" button in the JFrame (ie, on the top left) did the trick. But I agree with you it is kind of an unsettling solution. So I fiddled around and discovered a neater way to fix it. Just add the line

myChildOfJFrame.requestFocusInWindow();

to your main method, after you've created your instance of your subclass of JFrame and set it visible.


Hmm.. what class is your constructor for? Probably some class extending JFrame? The window focus should be at the window, of course but I don't think that's the problem.

I expanded your code, tried to run it and it worked - the key presses resulted as print output. (run with Ubuntu through 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);
    }
}

Deion (and anyone else asking a similar question), you could use Peter's code above but instead of printing to standard output, you test for the key code PRESSED, RELEASED, or 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;
}

If you don't want to register a listener on every component,
you could add your own KeyEventDispatcher to the 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);
    }
}

This should help

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

I got the same problem until i read that the real problem is about FOCUS the your JFrame has already added Listeners but tour frame is never on Focus because you got a lot of components inside your JFrame that also are focusable so try:

JFrame.setFocusable(true);

Good Luck


Hmm.. what class is your constructor for? Probably some class extending JFrame? The window focus should be at the window, of course but I don't think that's the problem.

I expanded your code, tried to run it and it worked - the key presses resulted as print output. (run with Ubuntu through 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);
    }
}

in order to capture key events of ALL text fields in a JFrame, one can employ a key event post processor. Here is a working example, after you add the obvious includes.

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

If you don't want to register a listener on every component,
you could add your own KeyEventDispatcher to the 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);
    }
}

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to swing

Calling another method java GUI Read input from a JOptionPane.showInputDialog box Call japplet from jframe Java JTable getting the data of the selected row What does .pack() do? How to add row of data to Jtable from values received from jtextfield and comboboxes How can I check that JButton is pressed? If the isEnable() is not work? Load arrayList data into JTable How to draw a circle with given X and Y coordinates as the middle spot of the circle? Simplest way to set image as JPanel background

Examples related to jframe

JFrame background image JFrame: How to disable window resizing? Adding image to JFrame How to make a JFrame button open another JFrame class in Netbeans? How to layout multiple panels on a jFrame? (java) How to add text to JFrame? JFrame.dispose() vs System.exit() JPanel vs JFrame in Java Adding JPanel to JFrame Limiting the number of characters in a JTextField

Examples related to keylistener

Keylistener in Javascript Allowing the "Enter" key to press the submit button, as opposed to only using MouseClick Key Listeners in python? How to use KeyListener KeyListener, keyPressed versus keyTyped Place cursor at the end of text in EditText Unresponsive KeyListener for JFrame