简体   繁体   中英

KeyListener on panel in java Swing. Wrong output

I want to move the white box up and down using 'w''s''a''d' keys. This is my code :

static int matrix[][] = { { 1, 1, 1, 1,1,1 }, { 1, 0, 0, 0,0,0 }, { 1, 3, 1, 1,0,0 }, {1,0,1,0,0,0}, {1,0,1,2,2,1}, {1,1,1,1,1,1}  };
JPanel easyPanel(){

    JPanel panel = new JPanel(new GridLayout(6, 6, 0, 0));


    int rowNumber = 0; 
    int colNumber = 0; 


    for (int i = 0; i < 36; i++) {
        if(colNumber == 6){
            colNumber = 0;
            rowNumber++; 
        }
        JLabel l = new JLabel();


        if(matrix[rowNumber][colNumber] == 0){
                l.setBackground(Color.pink);
            }
        else if(matrix[rowNumber][colNumber]==2){
            l.setIcon(new ImageIcon(new ImageIcon("cross.png").getImage().getScaledInstance(70, 70, Image.SCALE_DEFAULT)));


        }

else if(matrix[rowNumber][colNumber]==3){
                l.setIcon(new ImageIcon(new ImageIcon("icon.png").getImage().getScaledInstance(70, 70, Image.SCALE_DEFAULT)));
                int row = rowNumber;
                int col = colNumber;
                addKeyListener(new KeyListener() {

                @Override
                public void keyPressed(KeyEvent ke) {
                    //move();
                }
                @Override
                public void keyReleased(KeyEvent ke) {
                    //move();.
                }
                @Override
                public void keyTyped(KeyEvent ke) {
                    panel.setVisible(false);
                    matrix[row][col] = 0;
                    move(ke,row,col);
                }
            });
            }




   private void move(KeyEvent ke,int row,int col){
        if(ke.getKeyChar() == 'w'){
            System.out.println("Pressed up");
            matrix[row-1][col] = 3;
            JPanel newGame = easyPanel(); 
            newGame.setVisible(true);
            add(newGame); 

        }
        else if(ke.getKeyChar() =='s'){
            System.out.println("Pressed down");
            matrix[row+1][col] = 3;
            JPanel newGame = easyPanel(); 
            newGame.setVisible(true);
            add(newGame);
        }
        else if(ke.getKeyChar() == 'a'){
            System.out.println("Pressed left");
            matrix[row][col-1] = 3;
            JPanel newGame = easyPanel(); 
            newGame.setVisible(true);
            add(newGame);
        }
        else if(ke.getKeyChar() == 'd'){
            System.out.println("Pressed right");
            matrix[row][col+1] = 3;
            JPanel newGame = easyPanel(); 
            newGame.setVisible(true);
            add(newGame);
        }
        else
            System.out.println("Invalid Input");
    }

But i am getting output something like this : Default : 在此处输入图片说明

First Move 'w' - correct: 在此处输入图片说明

Next move 'd' - insted of moving a block, it moves makes two blocks white: 在此处输入图片说明

Where am I going wrong? Any help will be appreciated.

So based on this...

} else if (matrix[rowNumber][colNumber] == 3) {
    l.setIcon(new ImageIcon(new ImageIcon("icon.png").getImage().getScaledInstance(70, 70, Image.SCALE_DEFAULT)));
    int row = rowNumber;
    int col = colNumber;
    addKeyListener(new KeyListener() {

        @Override
        public void keyPressed(KeyEvent ke) {
            //move();
        }

        @Override
        public void keyReleased(KeyEvent ke) {
            //move();.
        }

        @Override
        public void keyTyped(KeyEvent ke) {
            panel.setVisible(false);
            matrix[row][col] = 0;
            move(ke, row, col);
        }
    });
}

Each time easyPanel is called and it finds a 3 in the matrix, it adds a new KeyListener , assuming you're updating the matrix correctly, this means that the first time it's called, you register one KeyListener , then the next time you call easyPanel , you add another and so and so forth.

The KeyListener should be registered separately and done so only once. In fact, I'd highly recommend using the key bindings API over KeyListener , as it will solve the focus related issues

I'd also consider a different update model. Instead of re-creating the UI each time, simply have another matrix of JLabel s, which is first created based on the matrix values.

You can then update the matrix

matrix[row][col] = 0;

Then update the label

updateUI(row, col);

which could do something like...

switch (matrix[row][col]) {
    case 0: labels[row][col].setIcon(null);
            break;  
    case 2: labels[row][col].setIcon(crossIcon);  
            break;  
    case 3: labels[row][col].setIcon(playerIcon);  
            break;  
}
repaint();

This will reduce the amount of overhead and reduce the risk of flickering.

You should also pre-cache and re-use your icons

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM