使用Key Listeners更改JFrame

时间:2015-02-24 18:45:59

标签: java swing user-interface jframe keylistener

我正在制作一个简单的Snake游戏,除了Key Listener之外,一切似乎都在工作。基于我所看到的一切正确写入。

游戏出现但即使按下箭头键,Snake也不会移动。

提前致谢!

这是主要的:

    public class SnakeFrame extends JFrame implements KeyListener{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int direction;
    private World w;
    private WorldComponant wc;
    GameLoopThread glt;

    public SnakeFrame(){
        setSize(420,440);
        setTitle("Snake");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container c = getContentPane();
        c.setLayout(new BorderLayout());

        w = new World();
        wc = new WorldComponant(w);
        glt = new GameLoopThread(wc);
        direction = Direction.SOUTH;

        c.add(wc);
    }

    public static void main(String[] args){
        SnakeFrame s = new SnakeFrame();
        s.setVisible(true);
    }

    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()){
        case (KeyEvent.VK_UP):{
            if(direction!=Direction.SOUTH){
                direction = Direction.NORTH;
                wc.move(direction);
            }
            break;
        }
        case (KeyEvent.VK_DOWN):{
            if(direction!=Direction.NORTH){
                direction = Direction.SOUTH;
                wc.move(direction);
            }
            break;
        }
        case (KeyEvent.VK_RIGHT):{
            if(direction!=Direction.WEST){
                direction = Direction.EAST;
                wc.move(direction);
            }
            break;
        }
        case (KeyEvent.VK_LEFT):{
            if(direction!=Direction.EAST){
                direction = Direction.WEST;
                wc.move(direction);
            }
            break;
        }
        }
}

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

}

这是GameLoopThread:

public class GameLoopThread extends Thread{

    private WorldComponant sc;

    public GameLoopThread(WorldComponant sc){
        this.sc = sc;
    }



    public void run(){
        while(true){
            sc.repaint();
            try{
                Thread.sleep(100);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

这是移动方法。它在世界级内部并且也从WorldComponant调用:

public void move(int direction) {
        Point head = snake.peekFirst();
        Point newPt = head;
        switch(direction){
        case (Direction.NORTH):{
            newPt = new Point(head.x, head.y-1);
            break;
        }
        case (Direction.SOUTH):{
            newPt = new Point(head.x, head.y+1);
            break;
        }
        case (Direction.WEST):{
            newPt = new Point(head.x-1, head.y);
            break;
        }
        case (Direction.EAST):{
            newPt = new Point(head.x+1, head.y);
            break;
        }

        }

        snake.remove(snake.peekLast());

        if(newPt.equals(food)){
            Point addPt = (Point) newPt.clone(); 

            switch(direction){
            case (Direction.NORTH):{
                newPt = new Point(head.x, head.y-1);
                break;
            }
            case (Direction.SOUTH):{
                newPt = new Point(head.x, head.y+1);
                break;
            }
            case (Direction.WEST):{
                newPt = new Point(head.x-1, head.y);
                break;
            }
            case (Direction.EAST):{
                newPt = new Point(head.x+1, head.y);
                break;
            }

            }
            score++;
            snake.add(addPt);
            placeFood();

        }
        else if(newPt.x < 0 || newPt.x > gridw - 1){
            generateDefaultSnake();
            JOptionPane.showMessageDialog(null, "YOU LOST! :(", "Loser!", JOptionPane.ERROR_MESSAGE);
            return;
        }
        else if(newPt.y < 0 || newPt.y > gridh - 1){
            generateDefaultSnake();
            JOptionPane.showMessageDialog(null, "YOU LOST! :(", "Loser!", JOptionPane.ERROR_MESSAGE);
            return;
        }
        else if(snake.contains(newPt)){
            generateDefaultSnake();
            JOptionPane.showMessageDialog(null, "YOU LOST! :(", "Loser!", JOptionPane.ERROR_MESSAGE);
            return;
        }

        snake.add(newPt);

    }

2 个答案:

答案 0 :(得分:0)

setFocusable(true)可见后,尝试在requestFocusInWindow()上致电JFrameJFrame。 (虽然,我认为setFocusable(true)对于JFrame来说并不是必需的。)

How to Write a Key Listener

How to Use the Focus Subsystem

答案 1 :(得分:0)

众所周知,

KeyListerner很麻烦,但在尝试将它们直接添加到JFrame时更糟糕。 JFrame在它与用户之间有一个JRootPanecontentPane,可能还有一个glassPane,所有这些都可以窃取焦点并阻止KeyListener接收关键事件

更好的解决方案是使用密钥绑定api并将其注册到自定义contentPane

有关详细信息,请参阅How to use key bindings