I am trying to get a circle to move through the input of a keyboard. I am not able to move the object at all. Can someone help me figure out what is wrong? Here is my code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class AlienInvader extends JPanel implements KeyListener{
Constants constant = new Constants();
public void update() {
constant.x += constant.xvel;
addKeyListener(this);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.MAGENTA);
g.fillOval(constant.x, constant.y, 30, 30);
repaint();
}
#Override
public void keyPressed(KeyEvent e) {
System.out.println(constant.x);
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
constant.xvel = -1;
break;
case KeyEvent.VK_RIGHT:
constant.xvel = 1;
break;
}
}
#Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_LEFT:
constant.xvel = -1;
break;
case KeyEvent.VK_RIGHT:
constant.xvel = 1;
break;
}
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
I am not sure what I am doing wrong. I thought it was because I wasn't calling the update method, but when I added a if statement in paintComponent (so it only calls itself once) and tried it, I had no luck.
To start with, don't call repaint within any paintXxx method. Paint methods are typically called in response to a call to repaint, therefore you are creating a nasty, never ending, ever consuming loop of resource hell.
Secondly, KeyListeners only respond to key events when 1- The component the are registered to are focusable 2- When the component they are registered to have focus.
They are a poor choice in this case. Use Key bindings instead
Thirdly, you are not providing a preferredSize hint for layout managers to use. This may or may not be a bad thing in your case, but it's possible that you component will be laid out with a size of 0x0
Example
Something like....
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class MoveCircle {
public static void main(String[] args) {
new MoveCircle();
}
public MoveCircle() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int xDelta = 0;
private int keyPressCount = 0;
private Timer repaintTimer;
private int xPos = 0;
private int radius = 10;
public TestPane() {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "pressed.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "pressed.right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "released.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "released.right");
am.put("pressed.left", new MoveAction(-2, true));
am.put("pressed.right", new MoveAction(2, true));
am.put("released.left", new MoveAction(0, false));
am.put("released.right", new MoveAction(0, false));
repaintTimer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
xPos += xDelta;
if (xPos < 0) {
xPos = 0;
} else if (xPos + radius > getWidth()) {
xPos = getWidth() - radius;
}
repaint();
}
});
repaintTimer.setInitialDelay(0);
repaintTimer.setRepeats(true);
repaintTimer.setCoalesce(true);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.drawOval(xPos, 0, radius, radius);
g2d.dispose();
}
public class MoveAction extends AbstractAction {
private int direction;
private boolean keyDown;
public MoveAction(int direction, boolean down) {
this.direction = direction;
keyDown = down;
}
#Override
public void actionPerformed(ActionEvent e) {
xDelta = direction;
if (keyDown) {
if (!repaintTimer.isRunning()) {
repaintTimer.start();
}
} else {
repaintTimer.stop();
}
}
}
}
}
For example...
Related
I have created a program that just moves a ball across a screen. I used to have it all in one class, but decided that it looked too messy so I split it up into three different classes: Main... initializes everything, Game... which paints everything and is a JPanel, and AL which is a KeyListener (which is also where the problem is). The problem is that I can't get the program to repaint from my AL class no matter what I try to pass into it. Can anyone help with this? Here are my three classes:
import java.awt.Color;
import javax.swing.JFrame;
public class Main {
static Game game;
static JFrame frame;
public static void main(String[] args) {
game = new Game();
frame = new JFrame();
frame.getContentPane().add(game);
frame.addKeyListener(new AL(game, frame));
frame.setTitle("Game");
frame.setSize(500, 500);
frame.setResizable(true);
frame.setVisible(true);
frame.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
-
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Game extends JPanel implements Runnable {
int x, y, xCoord, yCoord;
private Image dbImage;
private Graphics dbg;
JFrame frame;
public void changeCoord() {
x += xCoord;
y += yCoord;
if (x <= 20) {
x = 20;
}
if (x >= 480) {
x = 480;
}
if (y <= 40) {
y = 40;
}
if (y >= 480) {
y = 480;
}
}
public void setXCoord(int xcoord) {
xCoord = xcoord;
}
public void setYCoord(int ycoord) {
yCoord = ycoord;
}
public static void main(String[] args) {
Game game = new Game();
Thread t = new Thread(game);
t.start();
}
public Game() {
x = 250;
y = 250;
}
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
#Override
public void run() {
try {
while (true) {
changeCoord();
Thread.sleep(30);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
-
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
public class AL extends KeyAdapter {
Game game;
JFrame frame;
public AL(Game game, JFrame frame) {
this.game = game;
this.frame = frame;
}
#Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
game.setXCoord(-1);
}
if (keyCode == e.VK_RIGHT) {
game.setXCoord(+1);
}
if (keyCode == e.VK_UP) {
game.setYCoord(-1);
}
if (keyCode == e.VK_DOWN) {
game.setYCoord(+1);
}
game.repaint();
}
#Override
public void keyReleased(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == e.VK_LEFT) {
game.setXCoord(0);
}
if (keyCode == e.VK_RIGHT) {
game.setXCoord(0);
}
if (keyCode == e.VK_UP) {
game.setYCoord(0);
}
if (keyCode == e.VK_DOWN) {
game.setYCoord(0);
}
game.repaint();
}
}
Let's start with the obvious....
This is problematic...
#Override
public void paintComponent(Graphics g) {
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
#Override
public void paint(Graphics g) {
dbImage = createImage(getWidth(), getHeight());
dbg = dbImage.getGraphics();
paintComponent(dbg);
g.drawImage(dbImage, 0, 0, this);
}
There's no need to implement double buffering in Swing components, they already are. Also, you're breaking the painting contract, by not call the paint methods super methods
The whole thing should be...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
See Painting in AWT and Swing and Performing Custom Painting for more details
KeyListener is well known for been problematic. It will only raise key events if the component it registered to is focuable AND has keyboard focus. A JPanel by default, is not focusable. Before you run of and try and make it focusable (and get bitterly disappointed), you should be using the Key Bindings API instead, which was designed to over come the limitations of KeyListener
As a basic example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class Game extends JPanel {
int x, y, xCoord, yCoord;
public Game() {
x = 250;
y = 250;
addKeyBinding(KeyEvent.VK_LEFT, "move.left", new MoveAction(this, -1, 0));
addKeyBinding(KeyEvent.VK_RIGHT, "move.right", new MoveAction(this, 1, 0));
addKeyBinding(KeyEvent.VK_UP, "move.up", new MoveAction(this, 0, -1));
addKeyBinding(KeyEvent.VK_DOWN, "move.down", new MoveAction(this, 0, 1));
}
protected void addKeyBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
public void changeCoord() {
x += xCoord;
y += yCoord;
if (x <= 20) {
x = 20;
}
if (x >= 480) {
x = 480;
}
if (y <= 40) {
y = 40;
}
if (y >= 480) {
y = 480;
}
repaint();
}
public void setXCoord(int xcoord) {
xCoord = xcoord;
changeCoord();
}
public void setYCoord(int ycoord) {
yCoord = ycoord;
changeCoord();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(480, 480);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
}
public class MoveAction extends AbstractAction {
private int xDelta;
private int yDelta;
// I'd prefer an interface with just the "move" methods, but
// that's more time I don't have
private Game game;
public MoveAction(Game game, int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
this.game = game;
}
#Override
public void actionPerformed(ActionEvent e) {
game.setXCoord(xDelta);
game.setYCoord(yDelta);
}
}
}
But, wait, that isn't exactly what you want (trust me, I'm an anoymouse person on the Internet ;)), a better example might be...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum Direction {
UP,
LEFT,
DOWN,
RIGHT;
}
public class Game extends JPanel {
int x, y, xCoord, yCoord;
private Set<Direction> movement;
public Game() {
x = 250;
y = 250;
movement = new HashSet<>(4);
addKeyPressedBinding(KeyEvent.VK_LEFT, "left.pressed", new MoveAction(movement, Direction.LEFT, true));
addKeyReleasedBinding(KeyEvent.VK_LEFT, "left.released", new MoveAction(movement, Direction.LEFT, false));
addKeyPressedBinding(KeyEvent.VK_RIGHT, "right.pressed", new MoveAction(movement, Direction.RIGHT, true));
addKeyReleasedBinding(KeyEvent.VK_RIGHT, "right.released", new MoveAction(movement, Direction.RIGHT, false));
addKeyPressedBinding(KeyEvent.VK_UP, "up.pressed", new MoveAction(movement, Direction.UP, true));
addKeyReleasedBinding(KeyEvent.VK_UP, "up.released", new MoveAction(movement, Direction.UP, false));
addKeyPressedBinding(KeyEvent.VK_DOWN, "down.pressed", new MoveAction(movement, Direction.DOWN, true));
addKeyReleasedBinding(KeyEvent.VK_DOWN, "down.released", new MoveAction(movement, Direction.DOWN, false));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
changeCoord();
}
});
timer.start();
}
protected void addKeyBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0), name, action);
}
protected void addKeyPressedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, false), name, action);
}
protected void addKeyReleasedBinding(int keyCode, String name, Action action) {
addKeyBinding(KeyStroke.getKeyStroke(keyCode, 0, true), name, action);
}
protected void addKeyBinding(KeyStroke keyStroke, String name, Action action) {
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = getActionMap();
inputMap.put(keyStroke, name);
actionMap.put(name, action);
}
public void changeCoord() {
if (movement.contains(Direction.UP)) {
y--;
} else if (movement.contains(Direction.DOWN)) {
y++;
}
if (movement.contains(Direction.LEFT)) {
x--;
} else if (movement.contains(Direction.RIGHT)) {
x++;
}
x += xCoord;
y += yCoord;
if (x <= 20) {
x = 20;
}
if (x >= 480) {
x = 480;
}
if (y <= 40) {
y = 40;
}
if (y >= 480) {
y = 480;
}
repaint();
}
public void setXCoord(int xcoord) {
xCoord = xcoord;
changeCoord();
}
public void setYCoord(int ycoord) {
yCoord = ycoord;
changeCoord();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(480, 480);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval(x, y, 15, 15);
}
}
public class MoveAction extends AbstractAction {
private Set<Direction> movement;
private Direction direction;
private boolean pressed;
public MoveAction(Set<Direction> movement, Direction direction, boolean pressed) {
this.movement = movement;
this.direction = direction;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
movement.add(direction);
} else {
movement.remove(direction);
}
}
}
}
What this does is simply activates a flag when a key is pressed (and deactivates it when it's released), then in a Swing Timer, we check which keys are "active" and update the location of the ball.
What this does is, eliminates the key "stutter" which is caused by the OS when a key is first pressed and held. A delay is inserted between the first key and the repeated key events. Instead, we just turn the flag on and off as we like.
It also allows you to move in two directions at the same time (horizontally and vertically)
Have a look at Concurrency in Swing and How to use Swing Timers for more details
Although there are questions similar, I think mine is slightly different because of how I have my code set up. I have a JFrame within my main method. However, I only have JPanel in my constructor. I tried to make some of my variables static so that I could access them in the main method and say, for instance, if the x-coordinate of this graphic plus its width is greater than frame.getWidth().. but that won't work for some reason. I don't want to bombard anyone with code so I will just try to put the main information and if you need more, I'll update it.
package finalProj;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
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;
public class nonaMaingamePractice extends JPanel implements ActionListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static Ellipse2D ellipse;
static Toolkit tools = Toolkit.getDefaultToolkit();
static int screenWidth = (int)(Math.round(tools.getScreenSize().getWidth()));
static int screenHeight = (int)(Math.round(tools.getScreenSize().getHeight()));
private static Rectangle paddleRect;
JLabel text = new JLabel("cool");
Timer timeMove = new Timer(1, this);
Timer timeBall = new Timer(10, new timeBall());
private static double x = screenWidth/2, y = (screenHeight*0.8), xx = 0, yy = 0, score = 0, Ox = screenWidth/2, Oy = screenHeight/2, Oyy = 0, width = 100, height = 30;
public nonaMaingamePractice(){
setLayout(new BorderLayout());
timeBall.start();
timeMove.start();
addKeyListener(this);
setFocusable(true);
JPanel panelNorth = makePanel();
panelNorth.setBackground(Color.CYAN);
add(panelNorth, BorderLayout.NORTH);
JLabel scoreLabel = new JLabel("Score: " + score);
panelNorth.add(scoreLabel);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLUE);
paddleRect = new Rectangle((int)x, (int)y, (int)width, (int)height);
ellipse = new Ellipse2D.Double(Ox, Oy+Oyy, 50, 50);
Graphics2D graphics = (Graphics2D)g;
graphics.fill(paddleRect);
graphics.fill(ellipse);
}
#Override
public void actionPerformed(ActionEvent e) {
x = x + xx;
y = y + yy;
if(x<0){
x=0;
xx=0;
}
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
if(c==KeyEvent.VK_RIGHT){
xx=1;
}else if(c==KeyEvent.VK_LEFT){
xx=-1;
}
}
#Override
public void keyReleased(KeyEvent e) {
xx=0;
}
protected JPanel makePanel() {
#SuppressWarnings("serial")
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
};
pane.setBackground(Color.CYAN);
return pane;
}
protected class timeBall implements ActionListener{
Timer timeWhateva = new Timer(100, this);
#Override
public void actionPerformed(ActionEvent e) {
try{
System.out.println(paddleRect.getX());
if(ellipse.intersects(paddleRect)){
timeWhateva.start();
Oy+=-1;
System.out.println(ellipse.getX() + " " + ellipse.getY());
}else if(!ellipse.intersects(paddleRect)){
Oyy+=1;
}
}catch(RuntimeException NullPointerException){
System.out.println(NullPointerException.getMessage());
}
repaint();
}
}
public static void main(String[] args){
nonaMaingamePractice main = new nonaMaingamePractice();
JFrame frame = new JFrame();
frame.add(main);
frame.setVisible(true);
frame.setTitle("Project 4 game");
frame.setSize(screenWidth, screenHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Okay, so there seems to a few things that are wrong.
First, don't rely on static for cross object communication, this is a really bad idea which will come back to bite you hard. Instead, pass information to the classes which need it.
Second, I'd focus on having a single Timer (or "main-loop") which is responsible for updating the current state of the game and scheduling repaints. This is the basic concept of Model-View-Controller paradigm
The first thing I'm going to do is take your code apart completely and rebuild it...
To start with, I want some kind of interface which provides information about the current state of the game and which I can pass instances of to other parts of the game in order for them to make decisions and update the state of the game...
public interface GameView {
public boolean isKeyRightPressed();
public boolean isKeyLeftPressed();
public Dimension getSize();
public void updateState();
}
This provides information about the state of the right and left keys, the size of the view and provides some basic functionality to request that the view update it's current state
Next, we need some way to model the state of the game...
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
public interface GameModel {
public Rectangle getPaddle();
public Ellipse2D getBall();
public void ballWasMissed();
}
So, this basically maintains information about the paddle and ball and provides a means by which the "main game loop" can provide notification about the state of the game back to the model
Next, we need to the actual "main game loop" or controller. This is responsible for updating the state of the model and updating the view...
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
public class MainLoop implements ActionListener {
private GameView gameView;
private GameModel gameModel;
private int ballYDelta = 1;
public MainLoop(GameView gameView, GameModel gameModel) {
this.gameView = gameView;
this.gameModel = gameModel;
}
#Override
public void actionPerformed(ActionEvent e) {
Rectangle paddle = gameModel.getPaddle();
Ellipse2D ball = gameModel.getBall();
// Update the paddle position...
if (gameView.isKeyLeftPressed()) {
paddle.x--;
} else if (gameView.isKeyRightPressed()) {
paddle.x++;
}
// Correct for overflow...
if (paddle.x < 0) {
paddle.x = 0;
} else if (paddle.x + paddle.width > gameView.getSize().width) {
paddle.x = gameView.getSize().width - paddle.width;
}
// Update the ball position...
Rectangle bounds = ball.getBounds();
bounds.y += ballYDelta;
if (bounds.y < 0) {
bounds.y = 0;
ballYDelta *= -1;
} else if (bounds.y > gameView.getSize().height) {
// Ball is out of bounds...
// Notify the gameView so it knows what to do when the ball goes
// out of the game view's viewable, ie update the score...
// Reset ball position to just out side the top of the view...
gameModel.ballWasMissed();
bounds.y = -bounds.height;
} else if (paddle.intersects(bounds)) {
// Put the ball to the top of the paddle
bounds.y = paddle.y - bounds.height;
// Bounce
ballYDelta *= -1;
}
ball.setFrame(bounds);
// Update the view
gameView.updateState();
}
}
This is basically where we are making decisions about the current position of the objects and updating their positions. Here we check for "out-of-bounds" positions and update their states appropriately (for example, the ball can "bounce" and change directions)
The delta values are quite small, so you might want to play around with those
And finally, we need something that pulls it all together...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
public class NonaMaingamePractice extends JPanel implements KeyListener, GameView {
/**
*
*/
private static final long serialVersionUID = 1L;
JLabel text = new JLabel("cool");
private Timer timeBall;
private GameModel model;
private boolean init = false;
private boolean rightIsPressed;
private boolean leftIsPressed;
public NonaMaingamePractice() {
setLayout(new BorderLayout());
addKeyListener(this);
setFocusable(true);
JPanel panelNorth = makePanel();
panelNorth.setBackground(Color.CYAN);
add(panelNorth, BorderLayout.NORTH);
JLabel scoreLabel = new JLabel("Score: " + 0);
panelNorth.add(scoreLabel);
addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
if (getWidth() > 0 && getHeight() > 0 && !init) {
init = true;
model = new DefaultGameModel(getSize());
timeBall = new Timer(40, new MainLoop(NonaMaingamePractice.this, model));
timeBall.start();
} else if (model != null) {
model.getPaddle().y = (getHeight() - model.getPaddle().height) - 10;
}
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
Graphics2D graphics = (Graphics2D) g;
if (model != null) {
graphics.fill(model.getPaddle());
graphics.fill(model.getBall());
}
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
if (c == KeyEvent.VK_RIGHT) {
rightIsPressed = true;
} else if (c == KeyEvent.VK_LEFT) {
leftIsPressed = true;
}
}
#Override
public void keyReleased(KeyEvent e) {
int c = e.getKeyCode();
if (c == KeyEvent.VK_RIGHT) {
rightIsPressed = false;
} else if (c == KeyEvent.VK_LEFT) {
leftIsPressed = false;
}
}
protected JPanel makePanel() {
#SuppressWarnings("serial")
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
};
pane.setBackground(Color.CYAN);
return pane;
}
#Override
public boolean isKeyRightPressed() {
return rightIsPressed;
}
#Override
public boolean isKeyLeftPressed() {
return leftIsPressed;
}
#Override
public void updateState() {
// Maybe update the score??
repaint();
}
public static void main(String[] args) {
NonaMaingamePractice main = new NonaMaingamePractice();
JFrame frame = new JFrame();
frame.add(main);
frame.setVisible(true);
frame.setTitle("Project 4 game");
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
hi I want to draw horizontal and vertical axis in a panel by pressing h and v on keyboard . I don't know how ... this is my code . how can I control the Keytyped event
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import javax.swing.JPanel;
import java.awt.geom.Line2D;
#SuppressWarnings("serial")
public class DrawAxis extends JPanel implements KeyListener
{
private Graphics2D g2;
private float x1;
private float y1;
private float x2;
private float y2;
public void DrawingAxis(float X1,float Y1,float X2,float Y2)
{
x1=X1;
y1=Y1;
x2=X2;
y2=Y2;
}
public void paint(Graphics g)
{
super.paintComponent(g);
g2=(Graphics2D) g;
g2.setColor(Color.GRAY);
g2.setStroke(new BasicStroke(1));
g2.draw(new Line2D.Float(x1,y1,x2,y2));
}
#Override
public void keyPressed(KeyEvent event) {
}
#Override
public void keyReleased(KeyEvent event) {
}
#Override
public void keyTyped(KeyEvent event) {
char ch=event.getKeyChar();
switch(ch)
{
case 'h':
//????????
case 'v':
//????????
}
}
}
and this is the main code :
import javax.swing.JFrame;
public class Example1
{
public static void main(String[] args) {
JFrame frame=new JFrame("Drawing line");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1000,1000);
DrawAxis dshape=new DrawAxis();
dshape.DrawingAxis(500,0,500,1000);
dshape.DrawingAxis(0,500,1000,500);
dshape.setFocusable(true);
dshape.addKeyListener(dshape);
frame.add(dshape);
frame.setVisible(true);
}
}
how can I complete this code?
Start by using the key bindings API over KeyListener, it will solve some key issues associated with KeyListener. See How to Use Key Bindings for more details.
You could simply store a series of points in a array or List and use Graphics#drawLine to draw lines between them, or you could take advantage of Graphics 2D's shape API. See 2D Graphics for more details
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Path2D;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawLine {
public static void main(String[] args) {
new DrawLine();
}
public DrawLine() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Point currentPoint;
private Path2D shape;
public TestPane() {
currentPoint = new Point(0, 0);
shape = new Path2D.Double();
shape.moveTo(0, 0);
bindKey(KeyEvent.VK_H, "draw.horizontally", new AddPointAction(4, 0));
bindKey(KeyEvent.VK_V, "draw.vertically", new AddPointAction(0, 4));
}
protected void bindKey(int vkKey, String name, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(vkKey, 0), name);
am.put(name, action);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(shape);
g2d.dispose();
}
public class AddPointAction extends AbstractAction {
private int xDelta;
private int yDelta;
public AddPointAction(int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
int x = currentPoint.x + xDelta;
int y = currentPoint.y + yDelta;
shape.lineTo(x, y);
currentPoint.x = x;
currentPoint.y = y;
repaint();
}
}
}
}
I have been trying to find out how to move a rectangle with the arrow keys but there seems to be a problem.
I am using a KeyListener to detect all of the key inputs.
I do not know how to use a KeyBinding therefore I do not wish for the solution to have it.
I am planning to learn it right after mastering KeyListener. Please give me suggestions on how to fix it.
package expo;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Expo extends JPanel implements KeyListener{
int x = 0;
int y = 0;
#Override
public void keyTyped(KeyEvent e) {
//System.out.println("Key Typed");
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_DOWN){
System.out.println("Key Pressed" + e.getKeyCode());
y = y + 2;
}
}
#Override
public void keyReleased(KeyEvent e) {
//System.out.println("Key Released");
}
public void paint(Graphics g){
g.setColor(Color.BLUE);
g.drawRect(x ,y,100,100);
repaint();
}
public static void main(String[] args) throws InterruptedException {
Expo expo = new Expo();
JFrame f = new JFrame();
f.setVisible(true);
f.setSize(500,500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.addKeyListener(expo);
f.add(expo);
f.repaint();
}
}
Use the key bindings API over KeyListener, it solves the focus related issues that KeyListener suffers from. How to Use Key Bindings
Don't break the paint chain. If you override one of the paint methods, you must call it's super implementation.
Avoid overriding paint, it's normally to high in the paint process and because of the way painting works, doesn't always get called when a child component is painted, which can cause some interesting issues. Convention recommends using paintComponent instead. See Painting in AWT and Swing and Performing Custom Painting for more details
Try calling JFrame#setVisible last, after you have established the UI, you will find it causes less issues
As an example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Expo extends JPanel {
int x = 0;
int y = 0;
public Expo() {
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
y += 2;
if (y + 100 > getHeight()) {
y = getHeight() - 100;
}
repaint();
}
});
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
y -= 2;
if (y < 0) {
y = 0;
}
repaint();
}
});
}
public void bindKeyStrokeTo(int condition, String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(condition);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawRect(x, y, 100, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public static void main(String[] args) throws InterruptedException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Expo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
That's all cool and everything, but now, when you hold down the key, the rectangle moves, pauses and then begins to move steadily!?
This is actually quite normal. Instead, what you can do, is establish an "update loop" which constantly monitors the state of a set of flags, makes decisions about what to do when those flags are set and updates the UI.
So, what this does, is sets up a Swing Timer which ticks every 40 milliseconds, checks the state of the current "vertical key state", updates the y position accordingly and schedules a repaint, this allows for a much more smoother movement as we're not reliant on the repeating key stroke.
This also demonstrates the power of the key bindings API, as it establishes a single Action to handle both the up and down movements and the associated key releases...neat
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Expo extends JPanel {
int x = 0;
int y = 0;
public enum VerticalKey {
UP, DOWN, NONE;
}
public enum HorizontalKey {
LEFT, RIGHT, NONE;
}
private VerticalKey verticalKeyState = VerticalKey.NONE;
private HorizontalKey horizontalKeyState = HorizontalKey.NONE;
public Expo() {
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "pressed.down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), new VerticalAction(VerticalKey.DOWN));
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "released.down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), new VerticalAction(VerticalKey.NONE));
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "pressed.up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), new VerticalAction(VerticalKey.UP));
bindKeyStrokeTo(WHEN_IN_FOCUSED_WINDOW, "released.up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), new VerticalAction(VerticalKey.NONE));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
switch (verticalKeyState) {
case UP:
y -= 2;
break;
case DOWN:
y += 2;
break;
}
if (y + 100 > getHeight()) {
y = getHeight() - 100;
} else if (y < 0) {
y = 0;
}
repaint();
}
});
timer.start();
}
public void bindKeyStrokeTo(int condition, String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(condition);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawRect(x, y, 100, 100);
}
public void setVerticalKeyState(VerticalKey verticalKeyState) {
this.verticalKeyState = verticalKeyState;
System.out.println(verticalKeyState);
}
public void setHorizontalKeyState(HorizontalKey horizontalKeyState) {
this.horizontalKeyState = horizontalKeyState;
}
public class VerticalAction extends AbstractAction {
private VerticalKey verticalKey;
public VerticalAction(VerticalKey verticalKeys) {
this.verticalKey = verticalKeys;
}
#Override
public void actionPerformed(ActionEvent e) {
setVerticalKeyState(verticalKey);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
public static void main(String[] args) throws InterruptedException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Expo());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Just change these two pieces of code:
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_DOWN){
System.out.println("Key Pressed" + e.getKeyCode());
y = y + 2;
repaint();//add this line to update the UI
}
}
and
public void paint(Graphics g){
super.paint(g);//you should always call the super-method first
g.setColor(Color.BLUE);
g.drawRect(x ,y,100,100);
}
This would fix the issue. Though i'd recommend to override paintComponent instead of paint (read the section about "The Paint Methods" in this article: Painting in AWT and Swing). Basically the changes are i made change the following:
In keyPressed this line: repaint(); will update the UI after the square moved. Actually the square was moved before aswell, but the changes won't show until the UI is updated. In paint this line: super.paint(g); makes the panel do it's default painting first, which includes clearing the complete panel. And i've removed the repaint(); call, since it's completely useless.
NOTE:
if you use paintComponent instead of paint, you'll have to change the first call from super.paint(g) to super.paintComponent(g) to avoid a stackoverflow.
I've created a JFrame with a rectangle in the center of it that moves when I press certain keys. It's all nice and dandy, but the rectangle keeps going when I release the keys. In fact, if I press a key multiple times, the rectangle accelerates. This is probably (definitely) because I'm using a timer to get around that pesky 0.5-second input delay when holding a key down.
I think I have to put something in the keyReleased() method, but I'm at a loss for what to put there. Any tips? Thanks.
PS: Please don't yell at me for not using key bindings. I know: they're better and stuff. But I'm focusing on key listeners at the moment.
Program:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
#SuppressWarnings ("serial")
public class GameFrame extends JComponent implements KeyListener
{
static GameFrame gameFrame = new GameFrame();
public int x = 350;
public int y = 250;
public int keyCode;
public static void main (String[] args)
{
JFrame frame = new JFrame ("Java Game");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setSize (800, 600);
frame.setResizable (false);
frame.getContentPane().setBackground (Color.WHITE);
frame.getContentPane().add (gameFrame);
frame.addKeyListener (gameFrame);
frame.setVisible (true);
}
#Override
public void paintComponent (Graphics graphics)
{
super.paintComponent (graphics);
graphics.setColor (Color.BLACK);
graphics.fillRect (x, y, 100, 100);
}
public void keyPressed (KeyEvent event)
{
keyCode = event.getKeyCode();
new Timer (100, new ActionListener()
{
public void actionPerformed (ActionEvent event)
{
if (keyCode == KeyEvent.VK_LEFT)
{
x--;
repaint();
}
if (keyCode == KeyEvent.VK_RIGHT)
{
x++;
repaint();
}
if (keyCode == KeyEvent.VK_UP)
{
y--;
repaint();
}
if (keyCode == KeyEvent.VK_DOWN)
{
y++;
repaint();
}
}
}).start();
}
public void keyReleased (KeyEvent event) {}
public void keyTyped (KeyEvent event) {}
}
Avoid KeyListener, seriously, they are more trouble than they are worth, use the key bindings API instead. How to Use Key Bindings
There are a number of ways you might achieve this. One of the better way is to use a indirect approach. That is, the user presses a key and you raise a flag to indicate which is pressed, they release the key, you reset the flag, indicating that the key is no longer pressed.
You then use some kind of update loop to change the position of the object based which keys are currently active.
But why go to so much hassle I hear you ask. When a user presses a key, they is a short delay between the first key press and repeated key notification (while the key is down, the OS will send you key events until it is released), this makes the movement look a little "staggered".
Instead, we raise flag and use a constant update loop to make changes to the state of the object based on the state of the flags, which smooths out the key events, for example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test{
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
public enum HorizontalMovement {
NONE,
LEFT,
RIGHT
}
private HorizontalMovement horizontalMovement = HorizontalMovement.NONE;
private int xPos = 0;
public TestPane() {
addKeyPressedBinding("left.pressed", KeyEvent.VK_LEFT, new MoveHorizontialAction(HorizontalMovement.LEFT));
addKeyPressedBinding("right.pressed", KeyEvent.VK_RIGHT, new MoveHorizontialAction(HorizontalMovement.RIGHT));
addKeyReleasedBinding("left.relesed", KeyEvent.VK_LEFT, new MoveHorizontialAction(HorizontalMovement.NONE));
addKeyReleasedBinding("right.relesed", KeyEvent.VK_RIGHT, new MoveHorizontialAction(HorizontalMovement.NONE));
Timer timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
switch (horizontalMovement) {
case LEFT:
xPos--;
break;
case RIGHT:
xPos++;
break;
}
if (xPos < 0) {
xPos = 0;
} else if (xPos + 50 > getWidth()) {
xPos = getWidth() - 50;
}
repaint();
}
});
timer.start();
}
protected void addKeyPressedBinding(String name, int keyCode, Action action) {
KeyStroke ks = KeyStroke.getKeyStroke(keyCode, 0, false);
addKeyBinding(name, ks, action);
}
protected void addKeyReleasedBinding(String name, int keyCode, Action action) {
KeyStroke ks = KeyStroke.getKeyStroke(keyCode, 0, true);
addKeyBinding(name, ks, action);
}
protected void addKeyBinding(String name, KeyStroke ks, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(ks, name);
am.put(name, action);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle box = new Rectangle(xPos, (getHeight() - 50) / 2, 50, 50);
g2d.setColor(Color.BLUE);
g2d.fill(box);
g2d.dispose();
}
protected void addKeyBinding(String left, int VK_LEFT, MoveHorizontialAction moveHorizontialAction) {
throw new UnsupportedOperationException("Not supported yet.");
}
protected class MoveHorizontialAction extends AbstractAction {
private HorizontalMovement movement;
public MoveHorizontialAction(HorizontalMovement movement) {
this.movement = movement;
}
#Override
public void actionPerformed(ActionEvent e) {
horizontalMovement = movement;
}
}
}
}