I have a JFrame and on it a MainPanel that extends a JPanel. The MainPanel contains 2 other JPanels using the BorderLayout to arrange the view.
One of the Panel contains a button where the click event is triggered. But for the other Panel, the keybinding does not get triggered at all.
Here's the code for the MainClass that hold the 2 Panels
public class MainClass implements ... {
public JFrame frame;
JPanel highscore;
Board board;
Board.MoveAction moveAction;
@Override
public void init(Platform platform, int id) {
this.platform = platform;
this.selfId = id;
platform.setAbout("Hello ");
//platform.setSleepAfterSync(sleepPeriod);
frame = platform.createWindow(false);
// Create mainPanel to add all nested panels and buttons inside
JPanel mainPanel = new MainPanel();
mainPanel.add(board, BorderLayout.CENTER);
mainPanel.add(highscore, BorderLayout.PAGE_END);
frame.add(mainPanel);
frame.setTitle("Test");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(380, 440);
//frame.setBackground(Color.YELLOW);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public class MainPanel extends JPanel {
public MainPanel() {
setLayout(new BorderLayout());
//setBackground(Color.RED);
<-- the board here is the issue in the mainpanel-->
board = new Board(platform);
//board.setBackground(Color.BLUE);
highscore = new JPanel();
JButton button = new JButton("highscore");
button.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.print("highscore button");
}
});
highscore.add(button);
//highscore.setBackground(Color.GREEN);
}
}
And here is the code for the Board class that extends JPanel
public class Board extends JPanel implements ActionListener {
public Platform platform;
private int req_dx, req_dy, view_dx, view_dy;
private int IFW = JComponent.WHEN_IN_FOCUSED_WINDOW;
private final String MOVE_UP = "UP";
private final String MOVE_DOWN = "DOWN";
private final String MOVE_RIGHT = "RIGHT";
private final String MOVE_LEFT = "LEFT";
private final String START_GAME = "START";
public Board(Platform platform) {
this.platform = platform;
loadImages();
initVariables();
initBoard();
initKeyBinding();
}
private void initBoard() {
setBackground(Color.black);
setDoubleBuffered(true);
}
private void initVariables() {
...
...
}
..
..
..
..
public void initKeyBinding() {
System.out.println("HERE? init key binding -> yep ");
addKeyBinding(MOVE_UP, KeyEvent.VK_UP, new MoveAction(MOVE_UP, 0,-1));
addKeyBinding(MOVE_DOWN, KeyEvent.VK_DOWN, new MoveAction(MOVE_DOWN, 0,1));
addKeyBinding(MOVE_LEFT, KeyEvent.VK_LEFT, new MoveAction(MOVE_LEFT, -1 ,0));
addKeyBinding(MOVE_RIGHT, KeyEvent.VK_RIGHT, new MoveAction(MOVE_RIGHT, 1,0));
//this 's' to start is definitely wrong
//figure out how to change from if (key == 's' || key == 'S') to keybinding
//addKeyBinding(START_GAME, KeyEvent.VK_S, new MoveAction(START_GAME, KeyEvent.VK_S, KeyEvent.VK_S));
}
private void addKeyBinding(String name, int keyCode, AbstractAction action) {
//on keyRelease - true if the KeyStroke should represent a key release; false otherwise
// keyCode - an int specifying the numeric code for a keyboard key
// ie getInputMap(IFW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true/false), MOVE_UP);
getInputMap(IFW).put(KeyStroke.getKeyStroke(keyCode, 0), name);
getActionMap().put(keyCode, action);
}
public class MoveAction extends AbstractAction {
private int deltaX;
private int deltaY;
private String direction;
public MoveAction(String direction, int deltaX, int deltaY) {
this.direction = direction;
this.deltaX = deltaX;
this.deltaY = deltaY;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.print(direction);
switch (direction) {
case MOVE_UP:
System.out.println("up? ");
req_dx = 0;
req_dy = -1;
// do stuff that will move up
case MOVE_DOWN:
System.out.println("down? ");
req_dx = 0;
req_dy = 1;
// do stuff that will move down
// case START_GAME:
// System.out.println("sss");
// inGame = true;
// initGame();
}
}
}
}
I understand there are 4 components to note for KeyBinding
an Action ie actionPerformed {.. }
a KeyStroke ie (KeyStroke.getKeyStroke..)
an InputMap ie getInputMap(...)
an ActionMap ie getActionMap(...)
What am I missing for my keyboard event to be triggered in the MainPanel? thanks!
using this as reference KeyEvent keyPressed key combination is blocked managed to change keylisteners to keybinding instead
public void initKeyBinding() {
mapKeys = new HashMap<>();
mapKeys.put(MOVE_UP, false);
mapKeys.put(MOVE_DOWN, false);
mapKeys.put(MOVE_LEFT, false);
mapKeys.put(MOVE_RIGHT, false);
mapKeys.put(START_GAME, false);
mapKeys.put(PAUSE_GAME, false);
mapKeys.put(ESCAPE, false);
addKeyBinding(KeyEvent.VK_UP, MOVE_UP);
addKeyBinding(KeyEvent.VK_DOWN, MOVE_DOWN);
addKeyBinding(KeyEvent.VK_LEFT, MOVE_LEFT);
addKeyBinding(KeyEvent.VK_RIGHT, MOVE_RIGHT);
addKeyBinding(KeyEvent.VK_S, START_GAME);
addKeyBinding(KeyEvent.VK_ESCAPE, ESCAPE);
}
private void addKeyBinding(int keyCode, String name) {
// keyRelease - true if the KeyStroke should represent a key release; false otherwise
// keyCode - an int specifying the numeric code for a keyboard key
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, true), "pressed" + name);
inputMap.put(KeyStroke.getKeyStroke(keyCode, 0, false), "released" + name);
actionMap.put("pressed" + name, new KeyAction(name, true));
actionMap.put("released" + name, new KeyAction(name, false));
}
public class KeyAction extends AbstractAction {
private String name;
private boolean state;
public KeyAction(String name, boolean state) {
this.name = name;
this.state = state;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(name);
System.out.println(state);
mapKeys.put(name, state);
if (inGame) {
switch (name) {
case MOVE_UP:
req_dx = 0;
req_dy = -1;
break;
case MOVE_DOWN:
req_dx = 0;
req_dy = 1;
break;
case MOVE_RIGHT:
req_dx = 1;
req_dy = 0;
break;
case MOVE_LEFT:
req_dx = -1;
req_dy = 0;
break;
case ESCAPE:
if (timer.isRunning()) {
inGame = false;
}
break;
}
} else {
if (mapKeys.put(START_GAME, false)) {
inGame = true;
initGame();
}
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
repaint();
}