I am making a class (called Play), that extends JFrame, and implements ActionListener and KeyListener. This class does not hold the main() method, because there is a different class for that.
I am getting an error which states, "Class Play must either be declared abstract, or implement abstract method keyReleased(KeyEvent) in KeyListener".
import javax.swing.*;
import java.awt.*;
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 Play extends JFrame implements ActionListener, KeyListener {
Timer timer = new Timer(5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public Play() {
timer.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPreformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void left() {
vely = 0;
velx = -1.5;
}
public void right() {
vely = 0;
velx = 1.5;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
}
Well, do what it says. Since you're inheriting the KeyListener interface, you have to implement all of the interface's methods, including 'keyReleased'
The KeyListener must have all of it's methods implemented.
Simply add this method to the class and it should work
#Override
public void keyReleased(KeyEvent e) {
}
You must also Override all of the KeyListener implemented methods
Related
hi im trying to make a rectangle move up and down on key press in jframe.
but the rectangle only goes down when i press the up or down arrow key and it does not stop. and i cant see where i have made a mistake.
i don't think the mistake is in file one but as said, i cant find it so it maybe is.
file 1
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class test{
public static void main (String[] arg) {
JFrame window = new JFrame();
test2 t2 = new test2();
window.add(t2);
window.setSize(1000,1000);
window.setTitle("TEST");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}
}
file 2
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class test2 extends JPanel implements ActionListener, KeyListener{
Timer t = new Timer(5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public test2() {
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Rectangle((int)x, (int)y, 20, 40));
}
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP); {
up();
}
if (code == KeyEvent.VK_DOWN); {
down();
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
}
Your logic is not very optimal. You should have your code more like this:
/** DELETE THIS METHOD!
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}**/
private static final double MOVEMENT = 1.5;
public void up() {
x += -MOVEMENT; // Mind the - in front of MOVEMENT to negate the value.
// No need to change y if it does not change at all
repaint() // Repaint _after_ you changed the coordinates
}
public void down() {
x += MOVEMENT; // Mind that there is no - infront of this MOVEMENT.
// No need to change y if it does not change at all
repaint() // Repaint _after_ you changed the coordinates
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP); {
up();
}
if (code == KeyEvent.VK_DOWN); {
down();
}
}
You miss calling repaint() onYour JPanel after changing the position of x,y;
Also note that your events will only trigger twice (OnKeyDown and OnKeyUp).
Hey so I'm fairly new to java, but based on doing a lot of research and analyzing various code, I came up with some code to move a basic circle on a screen by using arrow keys.
However, for some reason, the code does not run the whole key event. If I press any key on the keyboard, even different arrow keys, it will cause the circle to only move one direction.
Based on my code, I feel like everything should work, but it just won't run the KeyEvent function properly. Any ways to fix it?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class second extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer(5, this);
int x = 0, y = 0, velx = 0, vely = 0;
public second()
{
t.start();
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPerformed(ActionEvent e)
{
x += velx;
y += vely;
repaint();
}
public void up()
{
velx = 0;
vely = 2;
}
public void down()
{
velx = 0;
vely = -2;
}
public void left()
{
velx = -2;
vely = 0;
}
public void right()
{
velx = 2;
vely = 0;
}
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP);
{
up();
}
if (keyCode == KeyEvent.VK_DOWN);
{
down();
}
if (keyCode == KeyEvent.VK_LEFT);
{
left();
}
if (keyCode == KeyEvent.VK_RIGHT);
{
right();
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
velx = 0;
vely = 0;
}
public static void main(String args[])
{
second s = new second();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
First of all, ActionListener is not required in this case. KeyListener is sufficient. Also there is a semicolon beside if statements, this is causing all the functions up, down, left and right to be invoked negating the effect.
Also for up, y should be reduced and for down, y should be increased.
Please find the below code which works fine. You can limit the right and down movement with MAX_LIMIT based on the window size. I limited it for 0,0 for left and up movement.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class Second extends JPanel implements KeyListener
{
int x = 0, y = 0;
public Second()
{
addKeyListener(this);
setFocusable(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void up()
{
if(y >= 5) {
y -= 5;
repaint();
}
}
public void down()
{
y += 5;
repaint();
}
public void left()
{
if(x >= 5) {
x -= 5;
repaint();
}
}
public void right()
{
x += 5;
repaint();
}
public void keyPressed(KeyEvent e)
{
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP)
{
up();
}
if (keyCode == KeyEvent.VK_DOWN)
{
down();
}
if (keyCode == KeyEvent.VK_LEFT)
{
left();
}
if (keyCode == KeyEvent.VK_RIGHT)
{
right();
}
}
public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
public static void main(String args[])
{
Second s = new Second();
JFrame f = new JFrame();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800, 600);
}
}
First, you have a semi-colon following your first if statement in keyPressed(), which impeaches considering following instructions. cf :
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_UP)
up();
if (keyCode == KeyEvent.VK_DOWN)
down();
if (keyCode == KeyEvent.VK_LEFT)
left();
if (keyCode == KeyEvent.VK_RIGHT)
right();
}
You also have a negative value for vely in down() where it should be positive (and vice-versa). And since you already reset velx and vely to 0 on keyReleased(), it is unnecessary to do it in your directions functions.
public void up() {
vely = -2;
}
public void down() {
vely = 2;
}
Class names should be CamelCase (not lowercase as presented).
Have fun.
I tried this code in BlueJ which should create a rectangle and move it around but it does not function. Then I put the same exact code into Eclipse and it functions as I thought it would. Any ideas to why this works in Eclipse but not in BlueJ?
import javax.swing.*;
import java.awt.*;
public class Shapes
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Test");
Draw object = new Draw();
frame.add(object);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Draw extends JPanel implements ActionListener, KeyListener
{
Timer tm = new Timer(5,this);
int x = 0, y = 0, velX = 0, velY = 0;
public Draw()
{
tm.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(x,y,100,20);
}
public void actionPerformed(ActionEvent e)
{
x += velX;
y += velY;
repaint();
}
public void keyPressed(KeyEvent e)
{
int c = e.getKeyCode();
if(c == KeyEvent.VK_LEFT)
{
velX = -1;
velY = 0;
}
if(c == KeyEvent.VK_UP)
{
velX = 0;
velY = 1;
}
if(c == KeyEvent.VK_RIGHT)
{
velX = 1;
velY = 0;
}
if(c == KeyEvent.VK_DOWN)
{
velX = 0;
velY = -1;
}
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e)
{
velX = 0;
velY = 0;
}
}
I can see what you mean I believe it attaches it to that corner of the screen because when I resize the screen it moves with that corner. I think its not that BlueJ can't Run it properly i believe it can but it does it differently than what eclipse does.
I believe this question asks the same thing and it gets pretty good answers you should look at it first.
I wrote a Java program that has 3 classes:
main.class (main method class)
Infout.class (class that draws circle + methods for circle that allow it to be controlled with keyboard input (arrow keys)
obj2.class (class that draws a rectangle)
All the code is compiled fine, but for some reason when I run the program, the program executes all the code from obj2.class but does not execute the one from Infout.class.
In other words, it draws the rectangle (obj2.class) but it does not draw the controllable circle (Infout.class). Is Obj2.class over riding Infout.class? If it is, what should I do?
The code is much too big to post here, the website says the post is "mostly code" :c.
Thanks!
EDIT: Ok here's the relevant code:
main.class
import javax.swing.JFrame;
public class main {
public static void main(String args[]) {
JFrame frame = new JFrame();
Infout m = new Infout();
obj2 o = new obj2();
frame.add(m);
frame.add(o);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 400);
frame.setTitle("Circle");
}
}
Infout.class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class Infout extends JPanel implements ActionListener, KeyListener {
Timer t = new Timer(5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public Infout(){
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 40, 40));
}
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
if (x < 0 || x > 260)
{
velx = 0;
vely = 0;
}
if (y < 0 || y > 340)
{
velx = 0;
vely = 0;
}
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void left() {
velx = -1.5;
vely = 0;
}
public void right() {
velx = 1.5;
vely = 0;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
}
obj2.class
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
public class obj2 extends JPanel{
int x;
int y;
public obj2(){
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(10, 20, 40, 40));
}
}
Infout and obj2 are not related.
Because obj2 extends JPanel, the call super.paintComponent(g) calls JPanel's version. If you obj2 to be a subclass of Infout, then you need to use extends:
public class obj2 extends Infout {
// Code here
}
Once this is done, super will refer to Infout.
So I was making a game for my Computer Science class, pretty much making a modified version of the game Frogger, and I first started off by just moving a circle across the JPanel to mimic the frogs movement and I realized a very annoying lag between the interactions with the buttons. Does anyone know how to completely get rid of the lag or perhaps reduce it? Any tips or help would be much appreciated! Here is the code so far for just the circle movement and if you see any improvements that could be done, please feel free to leave your comments.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
public class second extends JPanel implements ActionListener, KeyListener
{
Timer t = new Timer (5, this);
double x = 0, y = 0, velx = 0, vely = 0;
public second()
{
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paintComponent (Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.fill(new Ellipse2D.Double(x, y, 10, 10));
}
public void actionPerformed (ActionEvent e)
{
repaint();
x += velx;
y += vely;
}
public void up()
{
vely = -5;
velx = 0;
}
public void down()
{
vely = 5;
velx = 0;
}
public void left()
{
velx = -5;
vely = 0;
}
public void right()
{
velx = 5;
vely = 0;
}
public void upEnd()
{
velx = 0;
vely = 0;
}
public void downEnd()
{
velx = 0;
vely = 0;
}
public void leftEnd()
{
velx = 0;
vely = 0;
}
public void rightEnd()
{
velx = 0;
vely = 0;
}
public void keyPressed (KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP)
{
up();
}
if (code == KeyEvent.VK_DOWN)
{
down();
}
if (code == KeyEvent.VK_RIGHT)
{
right();
}
if (code == KeyEvent.VK_LEFT)
{
left();
}
}
public void keyTyped (KeyEvent e) {}
public void keyReleased (KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP)
{
upEnd();
}
if (code == KeyEvent.VK_DOWN)
{
downEnd();
}
if (code == KeyEvent.VK_RIGHT)
{
rightEnd();
}
if (code == KeyEvent.VK_LEFT)
{
leftEnd();
}
}
}
And here is the Main file:
import javax.swing.JFrame;
public class Macheads
{
public static void main (String[] args)
{
JFrame f = new JFrame();
second s = new second();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800,600);
}
}
Don't use a KeyListener. Instead you should be using Key Bindings.
The keyboard has a delay for repeating events. Use a Swing Timer to schedule the animation instead of relying on key events to be generated. See Motion Using the Keyboard for more information and examples.
Try using only the keyListener without the timer and actionlistener.
public void keyPressed (KeyEvent e)
{
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP)
{
up();
}
if (code == KeyEvent.VK_DOWN)
{
down();
}
if (code == KeyEvent.VK_RIGHT)
{
right();
}
if (code == KeyEvent.VK_LEFT)
{
left();
}
x += velx;
y += vely;
repaint(); //added and will repaint everytime key is pressed
}
//no need to place arguments in keyTyped and keyReleased because JPanel is repainted on keypressed...