Hello everyone I am new to Java so i think the answer to this question is very easy but I can't find out what part i'm doing wrong.. I added a keyListener to my pacman game but somehow it won't work.. i've used the following code:
package h04PacMan;
import java.awt.event.*;
import javax.swing.*;
public class PacManBediening extends JPanel implements ActionListener, KeyListener {
private JButton links, rechts, boven, beneden;
PacMan pacman;
public PacManBediening(PacMan pacman) {
this.pacman = pacman;
links = new JButton("<");
links.addActionListener(this);
add(links);
rechts = new JButton(">");
rechts.addActionListener(this);
add(rechts);
boven = new JButton("^");
boven.addActionListener(this);
add(boven);
beneden = new JButton("v");
beneden.addActionListener(this);
add(beneden);
}
/*
* bediening bij een klik
*/
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == links) {
pacman.setRichtingEnSnelheid( -10 );
pacman.setBesturing(0);
pacman.setView(180);
//System.out.println("links");
}
else if(e.getSource() == rechts) {
pacman.setRichtingEnSnelheid( +10 );
pacman.setBesturing(0);
pacman.setView(0);
//System.out.println("rechts");
}
else if(e.getSource() == boven) {
pacman.setRichtingEnSnelheid( -10);
pacman.setBesturing(1);
pacman.setView(90);
//System.out.println("boven");
}
else {
pacman.setRichtingEnSnelheid( +10);
pacman.setBesturing(1);
pacman.setView(270);
//System.out.println("beneden");
}
}
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_LEFT) {
pacman.setRichtingEnSnelheid( -10 );
pacman.setBesturing(0);
pacman.setView(180);
System.out.println("links");
}
else if(key == KeyEvent.VK_RIGHT) {
pacman.setRichtingEnSnelheid( +10 );
pacman.setBesturing(0);
pacman.setView(0);
System.out.println("rechts");
}
else if(key == KeyEvent.VK_UP) {
pacman.setRichtingEnSnelheid( -10);
pacman.setBesturing(1);
pacman.setView(90);
System.out.println("boven");
}
else if(key == KeyEvent.VK_DOWN) {
pacman.setRichtingEnSnelheid( +10);
pacman.setBesturing(1);
pacman.setView(270);
System.out.println("beneden");
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
can someone tell me what to add or do different?
You're missing a couple of lines in your PacManBediening constructor.
this.pacman = pacman;
this.setFocusable(true);
this.addKeyListener(this);
KeyListener isn't designated for Swing JComponents, I wouldn't going this way,
I think there is simple and possible to lost the Focus from focusable JComponents
use KeyBindings as most scallable workaround, rather that "catching or hunting for Focus" for KeyListener
for Swing JComponents are all internal short_cuts, key shortcuts, built_in methods, notifiers, based on KeyBindings
code example
Related
public void setUpButtonListeners() {
ActionListener buttonListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
Object o = ae.getSource();
if ((o == slots[3][1]) || (o == slots[3][2])) {
slideDown(slots);
} else if ((o == slots[0][1]) || (o == slots[0][2])) {
slideUp(slots);
} else if ((o == slots[1][3]) || (o == slots[2][3])) {
slideRight(slots);
} else if ((o == slots[1][0]) || (o == slots[2][0])) {
slideLeft(slots);
}
}
};
slots[3][1].addActionListener(buttonListener);
slots[3][2].addActionListener(buttonListener);
slots[0][1].addActionListener(buttonListener);
slots[0][2].addActionListener(buttonListener);
slots[1][3].addActionListener(buttonListener);
slots[2][3].addActionListener(buttonListener);
slots[1][0].addActionListener(buttonListener);
slots[2][0].addActionListener(buttonListener);
}
This the relevant code. I can find a ton of information on how to add keylisteners to specific JComponents but all I want to do is make it so that if(up arrow pressed) then slideUp(slots), instead of having to press JButtons on the screen to call these functions.
Edit:
Fixed, and it was really simple.
Added
frame.setFocusable(true);
frame.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
keyCode = e.getKeyCode();
switch (keyCode) {
case KeyEvent.VK_UP:
slideUp(slots);
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
});
to constructor.
Maybe you should use a custom KeyEventDispatcher to handle the arrow key events, otherwise you will have issues with the components focus.
KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
manager.addKeyEventDispatcher( new ArrowsKeyDispatcher() );
...
class ArrowsKeyDispatcher implements KeyEventDispatcher {
public boolean dispatchKeyEvent(KeyEvent e) {
if(e.getID() == KeyEvent.VK_UP) {
//Do something here when pressing UP ARROWKEY
}
// Do the same for all keys you need to handle globally
...
return false;
}
}
i am trying to take keyboard inputs to change the boolean's value but keylisteners are not working
those bolleans values will be used later in other class
heres the method i am having issues with
public boolean upPressed, downPressed, leftPressed, rightPressed;
#Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if(code == KeyEvent.VK_W){
upPressed = true;}
else if(code == KeyEvent.VK_S){
downPressed = true;}
else if(code == KeyEvent.VK_A){
leftPressed = true;}
else if(code == KeyEvent.VK_D){
rightPressed = true;}
}
i am using a different class which extends JPanel, frame is in a different class and key listener is in a different class and i have this.setFocusable(true);this.addKeyListener(keyH);
and if u want, here's the full code : https://github.com/PROMAN8625/2dGAME
Your code snippet looks fine. Maybe you didn't add KeyListener to the frame.
Here is a working example:
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Label;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyListenerExample implements KeyListener
{
public boolean upPressed, downPressed, leftPressed, rightPressed;
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_W) {
upPressed = true;
}
else if(code == KeyEvent.VK_S){
downPressed = true;}
else if(code == KeyEvent.VK_A){
leftPressed = true;}
else if(code == KeyEvent.VK_D){
rightPressed = true;}
System.out.println("The key Pressed was: " + e.getKeyChar());
System.out.println("upPressed: " + upPressed);
System.out.println("downPressed: " + downPressed);
System.out.println("leftPressed: " + leftPressed);
System.out.println("rightPressed: " + rightPressed);
System.out.println("\n");
}
#Override
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args)
{
//Setting the Frame and Labels
Frame f = new Frame("Demo");
f.setLayout(new FlowLayout());
f.setSize(500, 500);
Label l = new Label();
l.setText("This is a demonstration");
f.add(l);
f.setVisible(true);
//Creating and adding the key listener
KeyListenerExample k = new KeyListenerExample();
f.addKeyListener(k);
}
}
I will only supply the relevant parts of the code as it is quite large. Help me figure out why I never get keyboard events to the GameBoard JPanel. The game code runs just fine until I added the new feature where I wanted it to have a welcome screen.
Edit: If you would like to view the entire project (it's an eclipse project), here is the link to download it Eclipse project, I honestly can't format almost 1000 lines of code here on StackOverflow, that'll be painful even for you.
Main.java
private void initUI() throws IOException {
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
welcomeMenu = new Welcome(cardLayout, mainPanel);
mainPanel.add(welcomeMenu, "welcome");
game = new GameBoard();
mainPanel.add(game, "game");
add(mainPanel);
setTitle("Pacman");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(380, 420);
setLocationRelativeTo(null);
}
This is the welcome/menu panel (some section of it).
Welcome.java (servers as a menu)
#Override
public void actionPerformed(ActionEvent evt) {
if (evt.getActionCommand() == Actions.EXIT.name()) {
System.exit(0);
} else if (evt.getActionCommand() == Actions.CONFIG.name()) {
JOptionPane.showMessageDialog(null, "Not yet implemented");
} else if (evt.getActionCommand() == Actions.PLAY.name()) {
// The part that switches to game, works as expected.
cl.show(mp, "game");
}
}
GameBoard class has a KeyAdapter class within it that is used to listen to key events, however, in the addition of the new feature using CardLayout, I could not get the key events to the panel so my PacMan is just stuck in one place opening and closing its mouth like a fish.
GameBoard.java
private void initBoard() {
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.black);
initGame();
}
...
class TAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (inGame) {
if (key == KeyEvent.VK_LEFT) {
req_dx = -1;
req_dy = 0;
} else if (key == KeyEvent.VK_RIGHT) {
req_dx = 1;
req_dy = 0;
} else if (key == KeyEvent.VK_UP) {
req_dx = 0;
req_dy = -1;
} else if (key == KeyEvent.VK_DOWN) {
req_dx = 0;
req_dy = 1;
} else if (key == KeyEvent.VK_ESCAPE && timer.isRunning()) {
inGame = false;
} else if (key == KeyEvent.VK_PAUSE) {
if (timer.isRunning()) {
timer.stop();
} else {
timer.start();
}
}
} /*
* else { if (key == 's' || key == 'S') { inGame = true; initGame(); } }
*/
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == Event.LEFT || key == Event.RIGHT || key == Event.UP || key == Event.DOWN) {
req_dx = 0;
req_dy = 0;
}
}
}
The issue was using Key Listener when I should have been using Key Binding in the GameBoard JPanel. So instead of this,
class TAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (inGame) {
...
} else if (key == KeyEvent.VK_UP) {
req_dx = 0;
req_dy = -1;
} else if (key == KeyEvent.VK_DOWN) {
...
}
}
}
I replaced it with this approach (I will only demonstrate Arrow Up scenario),
private class UpAction extends AbstractAction {
private static final long serialVersionUID = 1L;
#Override
public void actionPerformed(ActionEvent e) {
if (!inGame)
return;
req_dx = 0;
req_dy = -1;
}
}
...
private void setupKeyListeners() {
getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "doUp");
...
getActionMap().put("doUp", new UpAction());
...
}
And later on,
private void initBoard() {
setupListeners();
setFocusable(true);
setBackground(Color.black);
initGame();
}
I'm trying to make a game in java, just a simple platformer, but I'm having difficulty when running the code. I can't seem to get any response from key presses. The only thing I can think hasn't been working properly is the keyPressed and keyReleased functions. Below is the relevant code.
public ReflexPanel() {
initBoard();
setFocusable(true);
addKeyListener(this);
Timer timer = new Timer(1000/120, this);
timer.start();
}
private void initBoard() {
loadMenu();
int w = menu.getWidth(this);
int h = menu.getHeight(this);
setPreferredSize(new Dimension(w, h));
}
private void step() {
if(mainMenu){
if(ePressed) {
System.exit(0);
}
if(hPressed) {
loadScores();
repaint();
}
}
}
public void keyTyped(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == 'e') {
ePressed = true;
}
if (e.getKeyCode() == 'h') {
hPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 'e') {
ePressed = false;
}
if (e.getKeyCode() == 'h') {
hPressed = false;
}
}
#Override
public void actionPerformed(ActionEvent e) {
step();
}
The ePressed and hPressed variables are just booleans set to false by default, and loadScores calls a png file.
You can't do this:
if(e.getKeyCode() == 'e'){
// code logic
}
KeyEvent::getKeyCode doesn't return the char you press on the keyboard. It "returns the integer keyCode associated with the key in this event". When using KeyEvent::getKeyCode you have to use the KeyEvent key constants values predefined in the class. So for example:
if(e.getKeyCode() == KeyEvent.VK_E){
// code logic
}
Or you can use KeyEvent::getKeyChar which "returns the character associated with the key in this event".
You're using getKeyCode() which returns an int value with constants given in KeyEvent class, such as KeyEvent.VK_E.
You're looking to use getKeyChar() which returns 'e' directly.
if (e.getKeyChar() == 'e') { // Now it has an actual chance of working
first class
private void spielfenster() {
setSize(1280, 720);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("");
setLayout(null);
setLocationRelativeTo(null);
addKeyListener(new Steuerung());
}
[...]
private void run() {
while(true){
if(we.nachRechts == true && we.mariox < (1280 - 38)){
we.mariox += 4;
repaint();
}
if(we.nachLinks == true && we.mariox > 0){
we.mariox -= 4;
repaint();
}
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
}
}
2nd class
package game;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class Steuerung extends KeyAdapter{
public Werte we = new Werte(); //object, to get access to the global values in class "Werte"
public void keyPressed(KeyEvent p){
int keys = p.getKeyCode();
if(keys == KeyEvent.VK_D){we.nachRechts = true;}
if(keys == KeyEvent.VK_S ){we.nachLinks = true;}
}
public void keyReleased(KeyEvent r){
int key = r.getKeyCode();
if(key == KeyEvent.VK_D){we.nachRechts = true;}
if(key == KeyEvent.VK_S ){we.nachLinks = true;}
}
}
New Problem: when i put this exact code of the key-listener in the class "Spielfenster" its working fine. Where is the problem?
2nd problem (bot not really important for me right now, but also good to know): if im creating an "Spielfenster" object in class "Steuerung" the frame opens himself about 10 times per sec. ?!
Thanks in previous! Palm