0

So I'm making a game, and my main Game application is running fine. The problem is, when I try to launch my game through a menu (using a button ActionEvent, for instance), my game can't seem to detect KeyEvents given to it. So I decided to make a bare-bones version of the code where the problem is:

class Response
{
    static JFrame frame;
    static BufferStrategy strategy;
    public Response()
    {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setUndecorated(true);
        frame.setIgnoreRepaint(true);
        frame.addKeyListener(new KeyAdapter() {
        public void keyTyped(KeyEvent e)
        {
            System.exit(0);
        }
        });
        frame.setVisible(true);
        frame.createBufferStrategy(2);
        strategy = frame.getBufferStrategy();

        frame.requestFocus();
    }
    public static void mainLoop()
    {
        while(true)
        strategy.show();
    }
}

class Button implements ActionListener
{
    JFrame f;
    JButton b;
    public Button()
    {
        f = new JFrame();
        f.setExtendedState(JFrame.MAXIMIZED_BOTH);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        b = new JButton("Click lol");
        b.setFocusable(false);
        b.addActionListener(this);
        f.add(b);
        f.setVisible(true);
        f.setFocusable(false);
    }

    public void actionPerformed(ActionEvent e)
    {
        f.dispose();
        new Response();
        Response.mainLoop();
    }

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

After clicking the button here, I get a blank screen, as expected, but it does not detect the KeyTyped event, and upon checking, it appears that Response.frame does not have the focus.

However, if I change the contents of main() to new Response(); Response.mainLoop();, the KeyEvent gets detected.

The setFocusable() methods have been called in the hopes that the components in Button pass on the focus to the Response frame. (After a few hours trying to find the solution, I have concluded that JFrames which use a BufferStrategy cannot be focused on (Although I haven't seen it written anywhere explicitly, so feel free to correct me).

Any idea what's happening?

Thanks in advance.

SaintSix_
  • 103
  • 2
  • `"I have concluded that JFrames which use a BufferStrategy cannot be focused on..."` -- yeah, that makes no sense at all. Why aren't you using [Key Bindings](https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) as any similar question on this site (which hopefully you searched), will tell you. – Hovercraft Full Of Eels Jan 14 '18 at 13:12
  • One of your problems is use of a tight loop which is hogging all CPU, in a needless and uncontrolled fashion. – Hovercraft Full Of Eels Jan 14 '18 at 13:13
  • @HovercraftFullOfEels, I'm not using Key Bindings because I'm working with an older version of Java, one that does not support them. And no, there is nothing I can do to change it, as it's in my college. I know that Key Bindings are way more efficient when it comes to detecting input for games and such, and I've used them before, sadly I can't use them in this case. – SaintSix_ Jan 15 '18 at 12:29
  • @HovercraftFullOfEels, in the actual game the looping condition is a boolean value. I just created this code in order to simulate the game code in a simple way. If you still think that it could be made better, feel free to offer suggestions. (I'm kind of new to Java and Swing) – SaintSix_ Jan 15 '18 at 12:33

1 Answers1

1

Generally the focus seems to be a rather slippery thing in java/swing. I have experienced that components do not have the focus even after calling specific methods that should give the focus to those components. After calling setFocusable() and, if present setEnabled() on any swing component, you should be able to set the focus on that component by clicking on it once the application is running and by what I know this is the best one can achieve and that is guaranteed to work. Never, though, rely on components just passing the focus on in the way you would like it. This is not likely to happen.

  • Thanks for answering! I tried calling `setFocusable()` followed immediately by `setEnabled()` after getting the BufferStrategy in `Response()`, and it still isn't working, even after I click on it. – SaintSix_ Jan 15 '18 at 12:39
  • 1
    OK, found the mistake! Your problem is, that your mainLoop() is running *all the time*. That means, the process has no time to react to your keyboard input. You need to do two things: First of all add a `Thread.sleep(longValueInMilliSecs)` after `strategy.show()` and curly brackets around the two invokes so that the `while`-loop is not eating up all your CPU power. Then, most important, start the `mainLoop()` in a new Thread with `new Thread(() -> {Response.mainLoop();}).start();`, so that the main Thread can react to the key input. –  Jan 15 '18 at 18:08