java keylistener not called

20,744

I'll bet that you're requesting focus before the JPanel has been rendered (before the top level window has either had pack() or setVisible(true) called), and if so, this won't work. Focus request will only be possibly granted after components have been rendered. Have you checked what your call to requestFocus() has returned? It must return true for your call to have any chance for a success. Also it's better to use requestFocusInWindow() rather than requestFocus().

But more importantly, you shouldn't be using KeyListeners for this but rather key bindings, a higher level concept that Swing itself uses to respond to key presses.

Edit
An example of an SSCCE:

import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

public class TestKeyListener extends JPanel {
   private KeyLis listener;

   public TestKeyListener() {
      add(new JButton("Foo")); // something to draw off focus
      listener = new KeyLis();
      this.setFocusable(true);
      this.requestFocus();
      this.addKeyListener(listener);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(300, 200);
   }

   private class KeyLis extends KeyAdapter {
      @Override
      public void keyPressed(KeyEvent e) {
         switch (e.getKeyCode()) {
         case KeyEvent.VK_LEFT:
            System.out.println("VK_LEFT pressed");
            break;
         case KeyEvent.VK_RIGHT:
            System.out.println("VK_RIGHT pressed");
            break;
         }
      }
   }

   private static void createAndShowGui() {
      TestKeyListener mainPanel = new TestKeyListener();

      JFrame frame = new JFrame("TestKeyListener");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Edit 2
And the equivalent SSCCE using Key Bindings:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class TestKeyBindings extends JPanel {

   public TestKeyBindings() {
      add(new JButton("Foo")); // something to draw off focus
      setKeyBindings();
   }

   private void setKeyBindings() {
      ActionMap actionMap = getActionMap();
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition );

      String vkLeft = "VK_LEFT";
      String vkRight = "VK_RIGHT";
      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), vkLeft);
      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), vkRight);

      actionMap.put(vkLeft, new KeyAction(vkLeft));
      actionMap.put(vkRight, new KeyAction(vkRight));

   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(300, 200);
   }

   private class KeyAction extends AbstractAction {
      public KeyAction(String actionCommand) {
         putValue(ACTION_COMMAND_KEY, actionCommand);
      }

      @Override
      public void actionPerformed(ActionEvent actionEvt) {
         System.out.println(actionEvt.getActionCommand() + " pressed");
      }
   }

   private static void createAndShowGui() {
      TestKeyBindings mainPanel = new TestKeyBindings();

      JFrame frame = new JFrame("TestKeyListener");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Edit 3
Regarding your recent SSCCE, your while (true) loops are blocking your Swing event thread and may prevent user interaction or painting from happening. Better to use a Swing Timer rather than while (true). For example:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;

import javax.swing.*;

public class BbbTest extends JFrame {

   private AreaOfGame areaOfGame;

   public BbbTest() {
      super("");
//      setVisible(true);
      this.setBackground(Color.darkGray);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.pack();
      setLayout(null);
      setBounds(200, 10, 400, 700);

      areaOfGame = new AreaOfGame();
      this.add(areaOfGame);
      setVisible(true);

      startGame();
   }

   public int generateNext() {
      Random r = new Random();
      int n = r.nextInt(7);
      return n;
   }

   public void startGame() {
      // while (!areaOfGame.GameOver()) {
      // areaOfGame.startGame(generateNext());
      // }

      areaOfGame.startGame(generateNext());
   }

   public static void main(String[] args) {
      new BbbTest();
   }

   class AreaOfGame extends JPanel {

      private static final int rightside = 370;

      private int bottom;
      private int top;

      private int currentPos;
      private int currentver;
      private KeyLis listener;

      public AreaOfGame() {
         super();

         bottom = 650;
         top = 50;
         setLayout(null);
         setBounds(20, 50, 350, 600);
         setVisible(true);

         this.setBackground(Color.lightGray);

         listener = new KeyLis();
         this.setFocusable(true);
         if (this.requestFocus(true))
            System.out.println("true");
         ;
         this.addKeyListener(listener);

         currentPos = 150;
         currentver = 0;
      }

      public void startGame(int n) {
         // while (verticallyInBound()) {
         // System.out.println("anything");
         // }

         int timeDelay = 50; // msecs delay
         new Timer(timeDelay , new ActionListener() {

            public void actionPerformed(ActionEvent arg0) {
               System.out.println("anything");
            }
         }).start();

      }

      public boolean verticallyInBound() {
         if (currentPos <= bottom - 50)
            return true;
         return false;
      }

      public boolean GameOver() {
         if (top >= bottom) {
            System.out.println("game over");
            return true;
         }

         else
            return false;
      }

      public boolean horizontalyInBounds() {
         if (currentPos <= rightside && currentPos >= 20)
            return true;
         else
            return false;
      }

      class KeyLis implements KeyListener {

         @Override
         public void keyPressed(KeyEvent e) {
            System.out.println("called");
            currentver += 5;
            switch (e.getKeyCode()) {
            case KeyEvent.VK_LEFT:
               if (horizontalyInBounds())
                  currentPos -= 5;
               break;
            case KeyEvent.VK_RIGHT:
               if (horizontalyInBounds())
                  currentPos += 5;
               break;
            }
            repaint();

         }

         @Override
         public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub

         }

         @Override
         public void keyTyped(KeyEvent e) {
            System.out.println("called 3");
         }
      }
   }
}
Share:
20,744
BBB
Author by

BBB

Updated on July 23, 2022

Comments

  • BBB
    BBB almost 2 years

    I have written a sample code using KeyListener in Java, I have created a JPanel, then set its focusable to true, I have created a KeyListener, requested a focus and then added the KeyListener to my panel. But the methods for the keyListener are never called. It seems although I have requested focus, it does not focus.

    Can anyone help?

    listener = new KeyLis();
    this.setFocusable(true);
    this.requestFocus();
    this.addKeyListener(listener);
    
     class KeyLis implements KeyListener{
    
        @Override
        public void keyPressed(KeyEvent e) {
            currentver += 5;
             switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5;  
                     break;
                case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5;  
                     break;
            }
            repaint();
        }
    
        @Override
        public void keyReleased(KeyEvent e) {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void keyTyped(KeyEvent e) {
        }
    }
    

    If any runnable code should be needed:

      import java.awt.Color;
      import java.awt.Graphics;
      import java.util.Random;
    
      import javax.swing.JFrame;
      import javax.swing.JLabel;
    
    
     public class test extends JFrame {
    
    private AreaOfGame areaOfGame;
    
    public test()
    {
        super("");
        setVisible(true);
        this.setBackground(Color.darkGray);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        setLayout(null);
        setBounds(200, 10, 400, 700);
    
        areaOfGame = new AreaOfGame();
        this.add(areaOfGame);
    
        startGame();
    }
    
    public int generateNext()
    {
        Random r = new Random();
        int n = r.nextInt(7);
        return n;
    }
    
    public void startGame()
    {
        while(!areaOfGame.GameOver())
        {
            areaOfGame.startGame(generateNext());
        }
    }
    
    
    public static void main(String[] args) {
        new MainFrame();
    }
    
    
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    import javax.swing.JPanel;
    
    public class AreaOfGame extends JPanel {
    
    
        private static final int rightside = 370;
    
        private int bottom;
        private int top;
    
        private int currentPos;
        private int currentver;
        private KeyLis listener;
    
        public AreaOfGame()
        {
            super();
    
            bottom = 650;
            top = 50;
            setLayout(null);
            setBounds(20, 50, 350, 600);
            setVisible(true);
    
    
            this.setBackground(Color.lightGray);
    
            listener = new KeyLis();
            this.setFocusable(true);
            if(this.requestFocus(true))
                System.out.println("true");;
            this.addKeyListener(listener);
    
    
            currentPos = 150;
            currentver=0;
        }
    
        public void startGame(int n)
        {
            while(verticallyInBound()){
                System.out.println("anything");
    
            }
    
    
        }
    
        public boolean verticallyInBound()
        {
            if(currentPos<= bottom -50)
                return true;
            return false;
        }
    
    
        public boolean GameOver()
        {
            if(top>= bottom){
                System.out.println("game over");
                return true;
            }
    
            else return false;
        }
    
    
        public boolean horizontalyInBounds()
        {
            if(currentPos<=rightside && currentPos>= 20)
                return true;
            else return false;
        }
    
    
    class KeyLis implements KeyListener{
    
            @Override
            public void keyPressed(KeyEvent e) {
                System.out.println("called");
                currentver += 5;
                 switch (e.getKeyCode()) {
                    case KeyEvent.VK_LEFT : if(horizontalyInBounds()) currentPos-= 5;  break;
                    case KeyEvent.VK_RIGHT: if(horizontalyInBounds()) currentPos+= 5;  break;
                }
                repaint();
    
    
            }
    
            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
    
            }
    
            @Override
            public void keyTyped(KeyEvent e) {
                System.out.println("called 3");
            }
    }
    
    }
    
  • BBB
    BBB over 12 years
    Actually these are all done after my frame has had pack() and setVisible(true).If using key bindings is the only choice I will do that, but I would really like to know why this does not work, because no body seemed to have this problem before, I checked for null pointers, for focuses, for methods being called, the listener being added, but non worked.
  • Hovercraft Full Of Eels
    Hovercraft Full Of Eels over 12 years
    @BBB: again, have you checked with your requestFocus() method call has returned? Is it returning true or false?
  • BBB
    BBB over 12 years
    it is returning false all the time
  • BBB
    BBB over 12 years
    this is actually what I have mentioned in my question, although I request, it seems it is not focused , meaning that it returns false and I dont know how to make it return true.
  • Hovercraft Full Of Eels
    Hovercraft Full Of Eels over 12 years
    @BBB: my point exactly. Then you have no hope for success unless you change something. Better if you could create and post a small compilable and runnable program that we can run and that demonstrates your problem so we can see it for ourselves, an sscce.
  • Hovercraft Full Of Eels
    Hovercraft Full Of Eels over 12 years
    @BBB: now an SSCCE that uses key bindings for illustrative purposes.
  • BBB
    BBB over 12 years
    Thankssss :D it is now called, i just added that JButton you added :D and now they get called, I dont have any idea why this might cause the listener to be called but thanks :D
  • BBB
    BBB over 12 years
    Thank you so much for all the help, I also added the timer, and now it works really fine :D Thanks for the time and help