在KeyPressed之后JPanel不会更新

时间:2013-10-27 20:56:11

标签: java swing jpanel keylistener

所以我试图用程序生成等来制作一个Roguelike游戏。但是我在处理字符时遇到了麻烦。 问题是,当我想用​​键盘移动角色时,它只是改变它的坐标 - 当然应该这样做,但我无法在屏幕上看到它。 我在这个网站上看到了一些答案,这对我有所帮助,但它并没有完全解决问题 所以,我注意到我做错了什么,这里有一些代码(希望它不会太长):

 
public class PanelTest extends JPanel implements KeyListener{


    private static final long serialVersionUID = 1L;
    private Game game;
    private int width, height;
    private int tileSize;

    public PanelTest(Game game, int tileSize) {
        super();

        this.game = game;
        this.tileSize = tileSize;
        this.width = game.getMap().getWidth()*tileSize;
        this.height = game.getMap().getHeight()*tileSize;

        this.addKeyListener(this);

        setPreferredSize(new Dimension(width, height));
        setRequestFocusEnabled(true);
        requestFocus();
        setVisible(true);

    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(int i=0; i < game.getMap().getWidth(); i++){
            for(int j=0; j < game.getMap().getHeight(); j++){
                g.setColor(game.getMap().getColor(i,j));
                g.fillRect(i*tileSize, j*tileSize, tileSize, tileSize);
            }
        }
// print the correct coordinates
        System.out.println(game.getPlayer().getX()+" "+game.getPlayer().getY());
    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        switch(e.getKeyCode()){
        case(KeyEvent.VK_Z) : game.getPlayer().moveUp();break;
        case(KeyEvent.VK_S) : game.getPlayer().moveDown(); break;
        case(KeyEvent.VK_Q) : game.getPlayer().moveLeft(); break;
        case(KeyEvent.VK_D) : game.getPlayer().moveRight(); break; 
        }
        revalidate();
        repaint();

    }

    public void addNotify() {
        super.addNotify();
        requestFocus();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    public static void main(String[] args){
        JFrame frame = new JFrame();
        frame.setBounds(0, 0, 400, 400);

        Map map = MapFactory.createNewEmptyMap();
        RoomMaker rm = new RoomMaker(map.getWidth()/7,map);
        TunnelMaker tm = new TunnelMaker(rm, map);
        rm.carveOut();
        tm.carveOut();
        Room r = rm.getRandomRoom();
        Player p = new Player(map, r.getxCenter(),r.getyCenter());
        Game game = new Game(map,p);

        frame.getContentPane().add(new PanelTest(game, 10));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }


}

希望你能帮忙,谢谢!

1 个答案:

答案 0 :(得分:1)

默认情况下,JPanel使用FlowLayout。

看起来您的代码正在更改玩家位置,但随后您调用revalidate()会导致调用布局管理器代码并重新计算组件的位置。

因此,对于随机移动的游戏,您希望使用空布局,并且不需要调用revalidate()和repaint(),因为您的代码不负责直接调用setLocation()方法。

有关使用keyListener的问题,另请参阅Motion Using the Keyboard

setRequestFocusEnabled(true);
requestFocus();
setVisible(true);

以上不需要。您设置为true的两个属性默认为true。除非组件显示在可见的GUI上,否则您无法请求关注组件,因此在此处添加该代码不会执行任何操作。另外,使用的正确方法是requestFocusInWindow(),而不是requestFocus()。