2

I'm writing a simple game, and I have main frame with 4 JPanels placed in CardLayout. Main frame looks like that:

private static JPanel[] panele = new JPanel[4];
private static JPanel panel;    
public GameWindow()
{
    super("Sokoban");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new BorderLayout());
    panele[0] = new MainMenu();
    panele[1] = new LoadGameMenu();
    panele[2] = new SaveGameMenu();     
    panele[3] = new GameScene();        
    panel = new JPanel(new CardLayout());

    //((MainMenu)panele[0]).setSaveOptionState(false);
    panel.add(panele[0], "MainMenu");
    panel.add(panele[1], "LoadGameMenu");
    panel.add(panele[2], "SaveGameMenu");
    panel.add(panele[3], "GameScene");      
    add(panel, BorderLayout.CENTER);


}

The GameScene panel have react to keyboard input. First I tried keylistener:

public GameScene() {        
    setFocusable(true);
    initWorld(); //Drawing on JPanel takes place here       
    addKeyListener(new Keyboard());         
}
class Keyboard extends KeyAdapter
{
    private int key;
    public void keyPressed(KeyEvent event)
    {
        System.out.println("Tu jestem");
        key = event.getKeyCode();
        if(key == KeyEvent.VK_ESCAPE)
        {
            Game.gra = new GameWindow(MenuAction.MAIN_MENU);
            System.out.println("Escape");
        }

That wasn't working... so I tried keybinding (simple implementation):

public GameScene() {    

    setFocusable(true);
    initWorld();  //Drawing on JPanel takes place here      
   // requestFocus();
    setInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, getInputMap());
    KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
    getInputMap().put(key, "pressed");      
    getActionMap().put("pressed", new AbstractAction(){         
        public void actionPerformed(ActionEvent arg0) {
            System.out.println("Spacja");
            //Game.gra = new GameWindow(MenuAction.MAIN_MENU);

        }

    });
}

It's still not working... I tried adding requestFocus and requestFocusInWindow() but with no effect. Any ideas how to fix it or to do it?

Solution have been found. In key binding I should write:

getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(key, "pressed");

insted of:

getInputMap().put(key, "pressed"); 
lukasz128
  • 45
  • 4

3 Answers3

3

Try this:

setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW));

Edit: For reference, "Each JComponent has one action map and three input maps."

Hakan Serce
  • 11,198
  • 3
  • 29
  • 48
  • I tried it... I got this error: Exception in thread "main" java.lang.IllegalArgumentException: WHEN_IN_FOCUSED_WINDOW InputMaps must be of type ComponentInputMap – lukasz128 May 20 '12 at 19:48
  • I guess you will also need to use `getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);` instead of `getInputMap()` – Hakan Serce May 20 '12 at 20:22
2

By using Action, illustrated here, you can bind a key (or combination) to that Action, as shown here. For additional guidance, please edit your question to include an sscce using either or both examples.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • As you can see in my code I do almost exact same thing like in your second link. Difference is that I don't want to bind the buttons actions to key interaction. In mainmenu I change Cards but when i change to GameScene I draw Board and using keyboard input I want to move character(Sokoban) – lukasz128 May 20 '12 at 19:58
  • 1
    I sounds like you want the bindings to change when the panel changes. Compare this [example](http://stackoverflow.com/a/10015234/230513) using `WHEN_ANCESTOR_OF_FOCUSED_COMPONENT` to this [example](http://stackoverflow.com/a/10186676/230513) using `WHEN_IN_FOCUSED_WINDOW`. – trashgod May 20 '12 at 20:11
  • 1
    It worked... thanks a lot. WHEN_IN_FOCUSED_WINDOW solved my problem. – lukasz128 May 20 '12 at 20:25
1

I don't know if this is what you really want but if you want to simply react to key event when you're in "GameScene" card you should switch to this card firstly (to grab focus):

        CardLayout cl = new CardLayout();
        panel = new JPanel(cl);
        ...
        add(panel, BorderLayout.CENTER);
        cl.show(panel, "GameScene");

Also looking at your code - consider using JMenu and/or JTabbedPane.

Xeon
  • 5,949
  • 5
  • 31
  • 52
  • I haven't mentioned it becouse I thought it's obvious. show method is called as an action for button click. I'm creating full screen game, so I can't use JMenu and I don't want the tab names to appear. – lukasz128 May 20 '12 at 19:13