2016-04-27 62 views
-1

我想编写一个程序,用户可以通过按WASD键在窗口上移动球。然而,当用户按下按键时,什么都不会发生。贝娄是我的程序代码,任何人都可以告诉我什么是错的,或者我该如何改进我的程序? (如果我删除的KeyListener,并把super.x ++球可以移动;在ball.move())Java GUI:如何使用WASD键移动球?

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){} 
} 

回答

4

然而,当用户按下按键,没有任何反应。

不要使用KeyListener的。 KeyListener只在组件具有焦点时才起作用,所以我猜测你的组件没有焦点。

而是使用Key Bindings,那么键盘甚至会工作,如果该组件没有焦点。

有关这两种方法的详细信息,请参阅Motion Using the Keyboard。以及两种方法的工作代码。

另外:

  1. 风俗画应该通过重载paintComponent(...)来完成,而不是油漆(...)。你应该在开始时调用super.paintComponent(...)。尽管在这种情况下,因为您正在扩展JComponent,所以后台将不会自动清除,因此您需要添加fillRect(...)语句以在绘制球之前绘制组件的背景。
  2. 不要使用的ScheduledThreadPoolExecutor动画。应该在事件调度线程上完成对GUI组件状态的更新。你应该使用Swing Timer。

看看Swing Tutorial。有Custom PaintingHow to Use Swing Timers部分为您开始。