Utkarsh Atri
Utkarsh Atri

Reputation: 67

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 : enter image description here

First Move 'w' - correct: enter image description here

Next move 'd' - insted of moving a block, it moves makes two blocks white: enter image description here

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

Upvotes: 1

Views: 76

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347294

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 JLabels, 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

Upvotes: 2

Related Questions