Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I want to write a program in which the user can move the ball on the window by pressing WASD keys. Yet, when the user presses the keys, nothing happens. Bellow are the codes of my program, can anyone tell me what's wrong or how can I improve my program? ( The ball can move if I delete the KeyListener and put super.x ++; in ball.move() )

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.swing.JApplet;
import javax.swing.JComponent;
import java.awt.geom.*;
public class MoveBall extends JApplet
{
    public final int Width =  567;
    public final int Height = 567;
    public static PaintSurface canvas;
    public void init()
    {
        canvas = new PaintSurface();
        this.setSize(Width, Height);
        this.add(canvas, BorderLayout.CENTER);
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(3);
        executor.scheduleAtFixedRate(new Action(), 0L, 10L, TimeUnit.MILLISECONDS);
    }
}
class Action implements Runnable
{
    public void run() 
    {
        MoveBall.canvas.repaint();  
    }   
}
class PaintSurface extends JComponent
{   
    Ball ball = new Ball(20);
    public PaintSurface()
    {
        addKeyListener(new Listener());
    }
    public void paint(Graphics g)
    {
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        ball.move();
        g2.setColor(Color.GREEN);
        g2.fill(ball);
        g2.setColor(Color.BLACK);
        g2.drawString("W,A,S,D or arrow keys to move", 7, 17);
    }
}
class Ball extends Ellipse2D.Float
{
    public int xspeed, yspeed;
    public Ball(int d)
    {
        super(370,370, d,d);
    }
    public void move()
    {
        if(super.x >567)
        super.x -=567;
        if(super.x <0)
        super.x +=567;
        if(super.y >567)
            super.y -=567;
        if(super.y < 0)
            super.y +=567;
        super.x += xspeed ;
        super.y += yspeed ;
    }
}
class Listener implements KeyListener
{
    public void keyPressed(KeyEvent ev) 
    {
        if(ev.getKeyCode() == KeyEvent.VK_W)
        {   
            MoveBall.canvas.ball.xspeed = 0 ;
            MoveBall.canvas.ball.yspeed = -1 ; 
        }   
        if(ev.getKeyCode() == KeyEvent.VK_A)
        {   
            MoveBall.canvas.ball.xspeed = -1 ;
            MoveBall.canvas.ball.yspeed = 0 ; 
        }   
        if(ev.getKeyCode() == KeyEvent.VK_S)
        {   
            MoveBall.canvas.ball.xspeed = 0 ;
            MoveBall.canvas.ball.yspeed = 1 ; 
        }   
        if(ev.getKeyCode() == KeyEvent.VK_D)
        {   
            MoveBall.canvas.ball.xspeed = 1 ;
            MoveBall.canvas.ball.yspeed = 0 ; 
        }   

    }
    public void keyReleased(KeyEvent arg0){}
    public void keyTyped(KeyEvent arg0){}
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
309 views
Welcome To Ask or Share your Answers For Others

1 Answer

Yet, when the user press the keys, nothing happens.

Don't use a KeyListener. A KeyListener only works if the component has focus, so I would guess your component doesn't have focus.

Instead use Key Bindings, then the keyboard will work even if the component doesn't have focus.

See Motion Using the Keyboard for more information about both approaches. As well as working code for both approaches.

Also:

  1. Custom painting should be done by overriding paintComponent(...), not paint(...). You should invoke super.paintComponent(...) at the start. Although in this case because you are extending JComponent the background will not be cleared automatically, so instead you need to add a fillRect(...) statement to paint the background of your component before painting the ball.
  2. Don't use a ScheduledThreadPoolExecutor for animation. Updates to the state of GUI components should be done on the Event Dispatch Thread. You should be using a Swing Timer.

Take a look at the Swing Tutorial. There are sections on Custom Painting and How to Use Swing Timers to get you started.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...