MainPanel 没有在嵌套的 JPanel 中监听 KeyBinding
MainPanel not listening to KeyBinding inside nested JPanel
我有一个 JFrame,它上面有一个扩展 JPanel 的 MainPanel。
MainPanel 包含另外 2 个使用 BorderLayout 排列视图的 JPanel。
其中一个面板包含触发点击事件的按钮。
但是对于另一个面板,键绑定根本不会被触发。
这是包含 2 个面板的 MainClass 的代码
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);
}
}
这里是 Board class 的代码,它扩展了 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();
}
}
}
}
我知道 KeyBinding 有 4 个组件需要注意
一个动作,即 actionPerformed {.. }
一个击键即(KeyStroke.getKeyStroke..)
一个 InputMap 即 getInputMap(...)
一个 ActionMap 即 getActionMap(...)
在 MainPanel 中触发我的键盘事件我错过了什么?谢谢!
以此为参考
设法将按键侦听器更改为按键绑定
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();
}
我有一个 JFrame,它上面有一个扩展 JPanel 的 MainPanel。 MainPanel 包含另外 2 个使用 BorderLayout 排列视图的 JPanel。
其中一个面板包含触发点击事件的按钮。 但是对于另一个面板,键绑定根本不会被触发。
这是包含 2 个面板的 MainClass 的代码
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);
}
}
这里是 Board class 的代码,它扩展了 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();
}
}
}
}
我知道 KeyBinding 有 4 个组件需要注意
一个动作,即 actionPerformed {.. }
一个击键即(KeyStroke.getKeyStroke..)
一个 InputMap 即 getInputMap(...)
一个 ActionMap 即 getActionMap(...)
在 MainPanel 中触发我的键盘事件我错过了什么?谢谢!
以此为参考
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();
}