Java 键侦听器和图形不一致

Java 键侦听器和图形不一致,java,swing,graphics,jframe,keylistener,Java,Swing,Graphics,Jframe,Keylistener,所以,嘿,我正试图制作一个基于Tron的光循环的简单游戏。它有3个类:使用main方法的驱动程序(LightCycleRunner)、存储每个灯光循环的坐标和方向的LightCycle类,以及在绘制背景后绘制和处理运动的类。一切都进行得很顺利,只是关键的听众在比赛结束后才肯听。我试图通过创建一个新线程来运行游戏来解决这个问题,同时让关键侦听器仍在侦听,但现在我的图形没有被识别。你的意见是什么 这是LightCycleRunner.java import java.awt.Event; impor

所以,嘿,我正试图制作一个基于Tron的光循环的简单游戏。它有3个类:使用main方法的驱动程序(LightCycleRunner)、存储每个灯光循环的坐标和方向的LightCycle类,以及在绘制背景后绘制和处理运动的类。一切都进行得很顺利,只是关键的听众在比赛结束后才肯听。我试图通过创建一个新线程来运行游戏来解决这个问题,同时让关键侦听器仍在侦听,但现在我的图形没有被识别。你的意见是什么

这是LightCycleRunner.java

import java.awt.Event;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class LightCycleRunner extends JFrame{

    /**
     *@param WIDTH the width of the window.
     *@param HEIGHT the height of the window.
     */
    private static final int WIDTH = 617;
    private static final int HEIGHT = 639;


    public LightCycleRunner()
    {
        super("Light Cycles");
        addKeyListener(this);
        setSize(WIDTH,HEIGHT);
        Grid obj = new Grid();
        getContentPane().add(obj);
        obj.giveCycles(cycle1, cycle2);
        setFocusable(true);
        setVisible(true);
    }

    public static void main( String args[] )
    {
        run();
    }
    public void run() {
            LightCycleRunner run = new LightCycleRunner();
            window = this.getGraphics();
        }

    public boolean handleEvent(Event e) {
        if (e.id == Event.KEY_PRESS) {
            System.out.println("pressed!!!!!!!!!!");
        } else if (e.id == Event.KEY_RELEASE) {
            System.out.println("pressed!!!!!!!!!!");
        }
        return false;
    }
}
这是Grid.java

import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.*;

public class Grid extends Canvas implements KeyListener, Runnable{

    final int FRAME_WIDTH = 600;
    final int FRAME_HEIGHT = 600;
    final int SQUARE_WIDTH = 20;
    final int SQUARE_HEIGHT = 20;
    final long WAITING_TIME = 300;
    Grid griddy = new Grid();
    Graphics window = griddy.getGraphics();
    griddy.paint(Graphics griddy);

    //to determine if the lightcycle will crash or not
    private boolean[][] instanceGrid = new boolean[30][30];
    //the two light players will control these light cycles
    LightCycle redCycle = new LightCycle(0,0,15);
    LightCycle blueCycle = new LightCycle(2,29,15);

    public void Grid(){
        setSize(FRAME_WIDTH,FRAME_HEIGHT);
        setBackground(Color.black);
        addKeyListener(this);
        setVisible(true);
        setFocusable(true);
    }

    public void giveCycles(LightCycle c1, LightCycle c2){
        redCycle = c1;
        blueCycle = c2;
    }

    public void run(){
        paint(this.getGraphics());
    }

    public void paint(Graphics window){
        /*
         *Draws Grid
         */
        window.setColor(Color.black);
        window.fillRect(0,0,600,600);
        //vertical lines
        window.setColor(Color.gray);
        for(int x = 0; x <= FRAME_WIDTH; x+=SQUARE_WIDTH){  
            window.drawLine(x,0,x,600);
        }
        //horizontal lines
        for(int y = 0; y <= FRAME_HEIGHT; y+=SQUARE_HEIGHT){
            window.drawLine(0,y,600,y);
        }

        //starting positions
        //red Cycle
        instanceGrid[redCycle.getY()][redCycle.getX()] = true;
        //blue Cycle
        instanceGrid[blueCycle.getY()][blueCycle.getX()] = true;

        public static void main(String[]args)
    {

        JFrame jp1 = new JFrame();
        Grid a=new Grid ();
        jp1.getContentPane().add(a, BorderLayout.CENTER);
        jp1.setSize(new Dimension(500,500));
        jp1.setVisible(true);

    }

        /*
         *Process pieces
         */
        new Thread() {
            public void run(){
                while(redCycle.isAlive()&&blueCycle.isAlive()){
                    //waiting period
                    System.out.println("***cycle started***");
                    this.getGraphics() = window;

                    try{
                        Thread.sleep(WAITING_TIME);
                    }
                    catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    //testing instanceGrid[][] for bugs
                    for(int row = 0; row < instanceGrid[0].length; row++){
                        for(int column = 0; column < instanceGrid.length; column++){
                            if(instanceGrid[row][column])
                                System.out.print("-");
                            else System.out.print("0");
                        }
                        System.out.println();
                    }
                    //red checks for obstructions
                    boolean redObstructed = false;
                    try{
                        switch(redCycle.getDirection()){
                            case 0: if(instanceGrid[redCycle.getY()][redCycle.getX()+1] == true)
                                //System.out.println(redCycle.getX()+1+","+redCycle.getY());
                                redObstructed = true; break;
                            case 1: if(instanceGrid[redCycle.getY()-1][redCycle.getX()] == true)
                                //System.out.println(redCycle.getX()+","+(redCycle.getY()-1));
                                redObstructed = true; break;
                            case 2: if(instanceGrid[redCycle.getY()][redCycle.getX()-1] == true)
                                //System.out.println(redCycle.getX()-1+","+redCycle.getY());
                                redObstructed = true; break;
                            case 3: if(instanceGrid[redCycle.getY()+1][redCycle.getX()] == true)
                                //System.out.println(redCycle.getX()+","+redCycle.getY()+1);
                                redObstructed = true; break;
                        }
                    }
                    catch(IndexOutOfBoundsException e){
                        redObstructed = true;
                    }


                    //kill red if crashed
                    if (redObstructed == true)
                        redCycle.kill();

                    //move and draw trails
                    if(redCycle.isAlive()){
                        //move
                        window.setColor(Color.red);
                        int x = redCycle.getX()*20+1;
                        int y = redCycle.getY()*20+1;
                        window.fillRect(x,y,SQUARE_WIDTH-1,SQUARE_HEIGHT-1);
                        redCycle.move();
                        instanceGrid[redCycle.getY()][redCycle.getX()] = true;
                        //window.drawLine(x1,y1,x2,y2);
                        x = redCycle.getX()*20+1;
                        y = redCycle.getY()*20+1;   

                        switch(redCycle.getDirection()){
                            case 0:
                                //update instanceGrid[][]
                                //draw triangle pointing right
                                //window.drawString("0",35,35);
                                window.drawLine(x,y,x,y+18);
                                window.drawLine(x,y,x+18,y+9);
                                window.drawLine(x,y+18,x+18,y+9);
                            break;
                            case 1:
                                //draw triangle pointing up
                                //window.drawString("1",35,35);
                                window.drawLine(x+9,y,x,y+18);
                                window.drawLine(x,y+18,x+18,y+18);
                                window.drawLine(x+9,y,x+18,y+18);
                            break;
                            case 2:
                                //draw triangle pointing left
                                //window.drawString("2",35,35);
                                window.drawLine(x+18,y,x+18,y+18);
                                window.drawLine(x,y+9,x+18,y);
                                window.drawLine(x,y+9,x+18,y+18);
                            break;
                            case 3:
                                //draw triangle pointing down
                                //window.drawString("3",35,35);
                                window.drawLine(x,y,x+18,y);
                                window.drawLine(x,y,x+9,y+18);
                                window.drawLine(x+18,y,x+9,y+18);
                            break;
                        }
                            //draw trails
                    }

                    boolean blueObstructed = false;
                    try{
                        switch(blueCycle.getDirection()){
                            case 0: if(instanceGrid[blueCycle.getY()][blueCycle.getX()+1] == true)
                                blueObstructed = true; break;
                            case 1: if(instanceGrid[blueCycle.getY()-1][blueCycle.getX()] == true)
                                blueObstructed = true; break;
                            case 2: if(instanceGrid[blueCycle.getY()][blueCycle.getX()-1] == true)
                                blueObstructed = true; break;
                            case 3: if(instanceGrid[blueCycle.getY()+1][blueCycle.getX()] == true)
                                blueObstructed = true; break;
                        }
                    }
                    catch(IndexOutOfBoundsException e){
                        blueObstructed = true;
                    }
                    if(blueObstructed == true)
                        blueCycle.kill();
                    if(blueCycle.isAlive()){
                        //move
                        window.setColor(Color.blue);
                        int x = blueCycle.getX()*20+1;
                        int y = blueCycle.getY()*20+1;
                        window.fillRect(x,y,SQUARE_WIDTH-1,SQUARE_HEIGHT-1);
                        blueCycle.move();
                        instanceGrid[blueCycle.getY()][blueCycle.getX()] = true;
                        //window.drawLine(x1,y1,x2,y2);
                        x = blueCycle.getX()*20+1;
                        y = blueCycle.getY()*20+1;

                        switch(blueCycle.getDirection()){
                            case 0:
                                //update instanceGrid[][]
                                //draw triangle pointing right
                                //window.drawString("0",35,35);
                                window.drawLine(x,y,x,y+18);
                                window.drawLine(x,y,x+18,y+9);
                                window.drawLine(x,y+18,x+18,y+9);
                            break;
                            case 1:
                                //draw triangle pointing up
                                //window.drawString("1",35,35);
                                window.drawLine(x+9,y,x,y+18);
                                window.drawLine(x,y+18,x+18,y+18);
                                window.drawLine(x+9,y,x+18,y+18);
                            break;
                            case 2:
                                //draw triangle pointing left
                                //window.drawString("2",35,35);
                                window.drawLine(x+18,y,x+18,y+18);
                                window.drawLine(x,y+9,x+18,y);
                                window.drawLine(x,y+9,x+18,y+18);
                            break;
                            case 3:
                                //draw triangle pointing down
                                //window.drawString("3",35,35);
                                window.drawLine(x,y,x+18,y);
                                window.drawLine(x,y,x+9,y+18);
                                window.drawLine(x+18,y,x+9,y+18);
                            break;
                        }
                            //draw trails
                    }
                    if(!(blueCycle.isAlive()||redCycle.isAlive())){
                        window.setColor(Color.white);
                        window.drawString("TIE",200,300);
                        System.out.println("TIE!");
                    }
                    else if(!blueCycle.isAlive()){
                        window.setColor(Color.white);
                        window.drawString("RED WINS!",200,300);
                        System.out.println("RED WINS!");
                    }
                    else{
                        window.setColor(Color.white);
                        window.drawString("BLUE WINS!",300,300);
                        System.out.println("BLUE WINS!");
                    }
                }
            }
        }.start();
    }
     /**
     *changes the direction of the light cycles according to which key was pressed
     */  
    public void keyPressed(KeyEvent e) {
        //System.out.println("KEY PRESSED");
        if(e.getKeyCode() == KeyEvent.VK_W)
        {redCycle.setDirection(1);
        System.out.println("RED UP");}
        else if(e.getKeyCode() == KeyEvent.VK_A)
        {redCycle.setDirection(2);
        System.out.println("RED LEFT");}
        else if(e.getKeyCode() == KeyEvent.VK_S)
        {redCycle.setDirection(3);
        System.out.println("RED DOWN");}
        else if(e.getKeyCode() == KeyEvent.VK_D)
        {redCycle.setDirection(0);
        System.out.println("RED RIGHT");}
        else if(e.getKeyCode() == KeyEvent.VK_UP)
        {blueCycle.setDirection(1);
        System.out.println("BLUE UP");}
        else if(e.getKeyCode() == KeyEvent.VK_LEFT)
        {blueCycle.setDirection(2);
        System.out.println("BLUE LEFT");}
        else if(e.getKeyCode() == KeyEvent.VK_DOWN)
        {blueCycle.setDirection(3);
        System.out.println("BLUE DOWN");}
        else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
        {blueCycle.setDirection(0);
        System.out.println("BLUE RIGHT");}
    }

    public void keyReleased(KeyEvent e) {
        //System.out.println("KEY RELEASED");
    }

    public void keyTyped(KeyEvent e) {
        //System.out.println("KEY TYPED");
    }

}

在我的评论中正式提出我的建议:

  • 如有必要,不要将AWT组件与Swing组件不必要地混合使用
    • 您将在一个GUI中混合重组件和轻组件,如果操作不正确,可能会导致副作用
    • 您将失去Swing默认双缓冲的优势
  • 使用JComponent或JPanel的
    paintComponent(…)
    方法绘制,而不是
    paint(…)
    方法。同样,这将为您提供Swing默认双缓冲的优势
  • 不要通过调用组件上的
    getGraphics()
    来获取图形对象,因为这将返回一个瞬间消失的对象,该对象很快将变为null,从而导致图像不稳定。”
    • 将背景图像绘制到BuffereImage要好得多,但请注意,可以调用
      getGraphics()
      为BuffereImage获取图形对象,但不要忘记在完成后处理它
    • 然后通过调用JVM传递到paintComponent(Graphics g)方法参数的图形对象上的
      drawImage(…)
      ,在
      paintComponent(…)
      覆盖中绘制BuffereImage
  • 再次使用JVM提供给您的图形对象,在
    paintComponent(…)
    方法中绘制任何短暂的或移动的图像
  • 不要处理JVM提供给您的图形对象
  • 您几乎从不直接调用
    paint(…)
    paintComponent(…)
    。我只是在打印一个组件或者我需要做一些像书中所示的非常奇特的图形时才这样做
  • 避免使用KeyListener,因为它们是低级构造,需要组件具有焦点。
    • 更好地使用键绑定——查看教程了解更多关于这些绑定的信息
    • 如果必须使用KeyListeners,则必须确保为listened to组件提供焦点
  • 查看
  • 还有这篇文章

我建议您改变很多事情。您的图形制作错误——您几乎不应该通过组件上的
getGraphics()
获取图形,您应该避免使用键侦听器,并使用键绑定,因为它们是更高级别的构造,在焦点方面更为宽容。您不应该混合使用Swing和AWT组件,您几乎不应该直接调用
paint(…)
,。。。在尝试这些东西之前,你真的应该阅读一些教程,因为猜测很少奏效。
import java.awt.event.*;

public class LightCycle{

    /* Cardinal directions
     * 0 = right
     * 1 = up
     * 2 = left
     * 3 = down 
     */
     /**
      *@param direction the cardinal direction the light cycle is facing (0=right, 1=up).
      *@param x the x coordinate from the left of the grid; 0 being the leftmost column.
      *@param y the y coordinate from the top of the grid; 0 being the top row.
      *@param alive whether or not the lightcycle has crashed or not
      */
    int direction;
    int x;
    int y;
    boolean alive = true;

    public LightCycle() {
        direction = 1;
        x = 0;
        y = 0;
    }

    /**
     *@param d the beginning direction the light cycle is facing
     *@param x1 the starting x coordinate.
     *@param y1 the starting y coordinate.
     */
    public LightCycle(int d, int x1, int y1) {
        direction = d;
        x = x1;
        y = y1;
    }


    /**
     *Changes the direction the light cycle is facing
     *@param d the new direction the light cycle will travel.
     */
    public void setDirection(int d){
        direction = d;
    }

   /**
    *changes either the x or y coordinates by 1 according to the direction 
    */
    public void move(){
        switch(direction){
            case 0: x++; break;
            case 1: y-- ; break;
            case 2: x--; break;
            case 3: y++; break;
        }
    } 
    /**
     *Sets alive to false.
     */
    public void kill(){
        alive = false;
    }

    /**
     *@return the direction the cycle is currently facing.
     */
    public int getDirection(){
        return direction;
    }

    /**
     *@return the current x coordinate.
     */
    public int getX(){
        return x;
    }

    /**
     *@return the current y coordinate.
     */
    public int getY(){
        return y;
    }

    /**
     *@return whether or not the lightcycle has crashed
     */
    public boolean isAlive(){
        return alive;
    }

}