ActionListener not working
when I press 'A' I don't do anything. I am making a game and I do not see any wrong writing of the code.
And if you have any sugestion on what to put in 2D simple survival game, please advise.
I am not getting any errors.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
public class Player extends JPanel implements ActionListener{
Timer time = new Timer(5, this);
double x = 0; double velX = 2;
double y = 0; double velY = 2;
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(x,y,40,40);
g2.fill(circle);
time.start();
}
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key == KeyEvent.VK_A){
System.out.println("VK_A"); // When i press 'A' don't print this
velX = 1;
x = 1;
x += velX;
x += 1;
//velY = 0;
}
}
public void actionPerformed(ActionEvent e){
//x += velX;
//y += velY;
//x = x + velX;
//y = y + velY;
repaint();
}
}
source to share
You don't have JButtons and are being called addActionListener(...)
to nothing, so it makes sense that this won't work. Solution: add a JButton and add an ActionListener to this button. Also, your question states that the ActionListener doesn't work, but your comment appears to be inside a non-existent KeyListener. This suggests that you really want to check out the Swing tutorials. You can find links to Swing tutorials and other Swing resources: Swing Info .
Other comments:
1) Re
I am not getting any errors.
The lack of compilation errors does not mean there are no logical errors (as you will find out).
2) Never start a timer from the paintComponent method. This method should only be for drawing and painting.
3) A
Use key bindings to respond to the press . The tutorials linked above will show you how to use them.
For example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import javax.swing.*;
// public class Player extends JPanel implements ActionListener {
public class Player extends JPanel { // !! avoid having GUI implement listener interfaces
private static final int TIME_DELAY = 15; // avoid magic numbers
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
Timer time = new Timer(TIME_DELAY, new TimerListener());
double x = 0;
double velX = 2;
double y = 0;
double velY = 2;
public Player() {
// start timer here!
time.start();
setKeyBindings();
}
private void setKeyBindings() {
// get action and input maps
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
// get keystroke
KeyStroke aKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);
// bind keystroke with an action
inputMap.put(aKeyStroke, aKeyStroke.toString());
actionMap.put(aKeyStroke.toString(), new A_Action());
}
@Override
//!! public void paintComponent(Graphics g) {
protected void paintComponent(Graphics g) { // should be protected not public
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
g2.fill(circle);
}
@Override //!! make bigger
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class A_Action extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("A key pressed");
x++;
y++;
repaint();
}
}
public void actionPerformed(ActionEvent e) {
// x += velX;
// y += velY;
// x = x + velX;
// y = y + velY;
repaint();
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// TODO: move x and y
repaint();
}
}
private static void createAndShowGui() {
Player mainPanel = new Player();
JFrame frame = new JFrame("Player");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Here is a more complete example that does all the movement in the Timer ActionListener. It uses an enumeration called "Direction" as well as a map that associates four direction enumeration values ββwith a boolean. Key bindings will change the Boolean value on the Map, and that's all. For example, if the up arrow is clicked, then the Map Boolean logic associated with Direction.UP will be correct. When the key has been released, the map value associated with the same Direction.UP key will be changed to false. The ActionListener timer will loop through the four direction enums, checking the map value for each enumeration, and then move the sprite in the direction indicated by the directive if the associated boolean is true. Benefits include the ability to respond to multiple keystrokes simultaneously:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;
@SuppressWarnings("serial")
public class MoveCircle extends JPanel {
private static final int TIME_DELAY = 15; // avoid magic numbers
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
Timer time = new Timer(TIME_DELAY, new TimerListener());
// key presses and releases will change the boolean values held in this Map
// When an arrow key is pressed, the direction-corresponding boolean is set true
// and likewise when the arrow key is released the direction corresponding boolean is false
private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
private double x = 0;
private double velX = 2;
private double y = 0;
private double velY = 2;
public MoveCircle() {
setKeyBindings();
time.start();
}
private void setKeyBindings() {
int condition = WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = getInputMap(condition);
ActionMap actionMap = getActionMap();
// iterate through all the Direction enums
for (Direction direction : Direction.values()) {
// set all values to false
dirMap.put(direction, false);
// create two key strokes, one for pressed and one for released
int keyValue = direction.getKeyValue();
KeyStroke pressedKey = KeyStroke.getKeyStroke(keyValue, 0, false);
KeyStroke releasedKey = KeyStroke.getKeyStroke(keyValue, 0, true);
// create two Actions, one for pressed, one for released
Action pressedAction = new KeyAction(direction, true);
Action releasedAction = new KeyAction(direction, false);
// add keystroke to inputMap and use keystroke toString as binding link
inputMap.put(pressedKey, pressedKey.toString());
inputMap.put(releasedKey, releasedKey.toString());
// link binding links to our actions
actionMap.put(pressedKey.toString(), pressedAction);
actionMap.put(releasedKey.toString(), releasedAction);
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// draw smooth circles
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
g2.fill(circle);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class KeyAction extends AbstractAction {
private Direction direction;
private boolean pressed;
public KeyAction(Direction direction, boolean pressed) {
this.direction = direction;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
dirMap.put(direction, pressed); // key press simply changes the map, that it.
}
}
private class TimerListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// if JPanel no longer displayed, stop the Timer
if (!MoveCircle.this.isDisplayable()) {
((Timer) e.getSource()).stop();
}
// here the key: iterate through the Direction enum
for (Direction direction : Direction.values()) {
// get corresponding boolean from dirMap
// and if true, change location of x and y
if (dirMap.get(direction)) {
x += velX * direction.getDeltaX();
y += velY * direction.getDeltaY();
}
}
repaint();
}
}
private static void createAndShowGui() {
MoveCircle mainPanel = new MoveCircle();
JFrame frame = new JFrame("Move Circle");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
enum Direction {
UP("Up", KeyEvent.VK_UP, 0, -1),
DOWN("Down", KeyEvent.VK_DOWN, 0, 1),
LEFT("Left", KeyEvent.VK_LEFT, -1, 0),
RIGHT("Right", KeyEvent.VK_RIGHT, 1, 0);
private String text;
private int keyValue; // KeyEvent.VK_?
private int deltaX;
private int deltaY;
Direction(String text, int keyValue, int deltaX, int deltaY) {
this.text = text;
this.keyValue = keyValue;
this.deltaX = deltaX;
this.deltaY = deltaY;
}
public String getText() {
return text;
}
public int getKeyValue() {
return keyValue;
}
@Override
public String toString() {
return text;
}
public int getDeltaX() {
return deltaX;
}
public int getDeltaY() {
return deltaY;
}
}
source to share