2016-04-27 16 views
-1

Ich möchte ein Programm schreiben, in dem der Benutzer den Ball durch Drücken der WASD-Tasten auf dem Fenster bewegen kann. Wenn der Benutzer jedoch die Tasten drückt, passiert nichts. Wie lauten die Codes meines Programms? Kann mir jemand sagen, was falsch ist oder wie kann ich mein Programm verbessern? (Der Ball kann sich bewegen, wenn ich die KeyListener löschen und setzen super.x ++; in ball.move())Java GUI: Wie man einen Ball mit WASD-Tasten bewegt?

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

Antwort

4

Doch wenn der Benutzer drücken Sie die Tasten, passiert nichts.

Verwenden Sie keinen KeyListener. Ein KeyListener funktioniert nur, wenn die Komponente den Fokus hat, also würde ich annehmen, dass Ihre Komponente keinen Fokus hat.

Verwenden Sie stattdessen Key Bindings, dann funktioniert die Tastatur auch, wenn die Komponente keinen Fokus hat.

Weitere Informationen zu beiden Ansätzen finden Sie unter Motion Using the Keyboard. Sowie Arbeitscode für beide Ansätze.

auch:

  1. Individuelle Malerei sollte durch zwingende paintComponent(...), nicht malen (...) erfolgen. Sie sollten super.paintComponent (...) am Anfang aufrufen. Obwohl in diesem Fall JComponent erweitert wird, wird der Hintergrund nicht automatisch gelöscht. Stattdessen müssen Sie eine fillRect (...) -Anweisung hinzufügen, um den Hintergrund Ihrer Komponente zu zeichnen, bevor Sie den Ball malen.
  2. Verwenden Sie keinen ScheduledThreadPoolExecutor für die Animation. Aktualisierungen des Status von GUI-Komponenten sollten im Event-Dispatch-Thread vorgenommen werden. Sie sollten einen Swing Timer verwenden.

Werfen Sie einen Blick auf die Swing Tutorial. Es gibt Abschnitte auf Custom Painting und How to Use Swing Timers, um Sie zu beginnen.