23

I have a JPanel inside a JFrame. I have registered a KeyListener, based on which I want to update the JPanel. The problem I am having is that I cannot get the focus on the JPanel and therefore my KeyListener won't work. I already know that the KeyListener is functional because I registered it with the JFrame and it worked fine. My code goes something like this at the moment:

myFrame.setFocusable(false);
myPanel.setFocusable(true);
myPanel.addKeyListener(myKL);
myFrame.add(myPanel);

Has anyone encountered a problem like this before? Is there something I am missing in regards to this?

P.S.: I do not have any components inside the JPanel I just draw an Image on the background, so I need the focus to be on the JPanel itself and not on something inside it.

Lukas Rotter
  • 4,158
  • 1
  • 15
  • 35
Vlad T.
  • 265
  • 1
  • 3
  • 5
  • 1
    Hmm, with adding myPanel.requestFocus() this works for me. What version of Java are you running? – Joshua McKinnon Jan 25 '10 at 20:35
  • 1
    Maybe post a SSCCE(simple self contained compilable example) that reproduces this. That will give others something to work w/ to help. I have also notices w/ a problem by narrowing it down to the smallest scope, sometimes I am able to find the solution myself. – broschb Jan 25 '10 at 21:37

5 Answers5

25

Although you're indicating that the panel can be focusable, the panel isn't asking for focus. Try using myPanel.requestFocus();.

David Koelle
  • 20,726
  • 23
  • 93
  • 130
  • Thanks for your answer. Tried both requestFocus() and requestFocusInWindow(), neither of them make the Panel get focus. Do you have any other suggestions? – Vlad T. Jan 25 '10 at 20:20
  • 4
    It may depend on when you call it. Don't call it in the JPanel's constructor, for example, since that gets called before the panel is displayed. – David Koelle Jan 26 '10 at 05:16
  • Thank you David, this answer worked for me, I had no idea that I couldn't make the call from the constructor. As soon as I moved the requestFocus() to a method that was getting called after the display on the screen it worked perfectly. – Vlad T. Jan 26 '10 at 06:20
  • 1
    For me I just needed to add this line on a `JScrollPane` to navigate with default key bindings. `public void mouseEntered(MouseEvent e) { e.getComponent().requestFocus(); }`. – bric3 Feb 06 '22 at 16:02
7

Use setFocusable(true) and then requestFocusInWindow(). But the latter must be done after the window containing the panel is made visible, for which you will likely need to register a window listener and do the requestFocusInWindow() in the window activated handler code.

Note: Specifically after the window is visible, not just after calling setVisible(true).

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
  • So how can my code tell _when_ the window ***is*** visible, if waiting until after `setVisible(true)` is called is insufficient? – Gavin S. Yancey Jul 10 '19 at 03:02
  • 1
    For me, it worked when I called `panel.requestFocusInWindow()` after `frame.pack()`. – notTypecast Feb 07 '20 at 22:15
  • Generally, wrapping Swing commands into a `SwingUtilities.invokeLater(()->{...});`, even if you're already on the Swing thread, can solve such problems, because (Docs say) "This will happen after all pending AWT events have been processed." For example: If you want to protect Swing event code from causing its own execution, you can set a boolean at the beginning, and at the end you reset the boolean, but the latter has to be in an invokeLater(), else the reset is too early in the event sequence. – Dreamspace President Sep 28 '20 at 08:24
2

I sometimes face a similar problem. I've noticed that in some cases it is better to make or request focus on a specific control within the panel that is within the frame (e.g., the input box to which you want keyboard input to go), rather than request focus for the pane itself.

Uri
  • 88,451
  • 51
  • 221
  • 321
2

Try

panel.setFocusable(true);
panel.setRequestFocusEnabled(true);

// some code here

panel.grabFocus();
John Doe
  • 869
  • 5
  • 10
2

Try something like this:

    myFrame.addFocusListener(new FocusAdapter() {

        /**
         * {@inheritDoc}
         */
        @Override
        public void focusGained(FocusEvent aE) {
            myPanel.requestFocusInWindow();
        }
    });
Bram Janssens
  • 146
  • 1
  • 5