Question

I'm writing a Tetris game and most of my mechanism is done. I tried to input my keyboard interaction creating a new KeyListener, but it simply doesn't seem to work, as I press the buttons the pieces just keep falling instead of changing their position. Could anybody help me please?

GUI Class:

package tetris;

import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JLabel;

public class Game extends javax.swing.JFrame {
Library obj = new Library();

public Game() {
    initComponents();

    jPanel1.setLayout(new GridLayout(15,20));
    for(int i = 0; i<15; i++){
        for(int j = 0; j<20; j++){
            JLabel label = new JLabel();
            label.setSize(15, 15);
            label.setIcon(new ImageIcon(getClass().getResource("whitetile.png")));
            jPanel1.add(label);
            obj.setTiles(i, j, label);
            label.addKeyListener(new KeyListener());
            this.setFocusable(true);
            this.requestFocusInWindow();
        }
    }
    obj.start();
}

private class KeyListener extends KeyAdapter{

    @Override
    public void keyPressed(KeyEvent evt){
        if(evt.getKeyChar() == KeyEvent.VK_LEFT){
            obj.tiles[obj.r1][obj.col1].setIcon(obj.white);
            obj.tiles[obj.r2][obj.col2].setIcon(obj.white);
            obj.tiles[obj.r3][obj.col3].setIcon(obj.white);
            obj.tiles[obj.r4][obj.col4].setIcon(obj.white);
            obj.col1 -= 1;
            obj.col2 -= 1;
            obj.col3 -= 1;
            obj.col4 -= 1;

            obj.tiles[obj.r1][obj.col1].setIcon(obj.red);
            obj.tiles[obj.r2][obj.col2].setIcon(obj.red);
            obj.tiles[obj.r3][obj.col3].setIcon(obj.red);
            obj.tiles[obj.r4][obj.col4].setIcon(obj.red);
        }

        if(evt.getKeyChar() == KeyEvent.VK_RIGHT){
            obj.tiles[obj.r1][obj.col1].setIcon(obj.white);
            obj.tiles[obj.r2][obj.col2].setIcon(obj.white);
            obj.tiles[obj.r3][obj.col3].setIcon(obj.white);
            obj.tiles[obj.r4][obj.col4].setIcon(obj.white);
            obj.col1 += 1;
            obj.col2 += 1;
            obj.col3 += 1;
            obj.col4 += 1;

            obj.tiles[obj.r1][obj.col1].setIcon(obj.red);
            obj.tiles[obj.r2][obj.col2].setIcon(obj.red);
            obj.tiles[obj.r3][obj.col3].setIcon(obj.red);
            obj.tiles[obj.r4][obj.col4].setIcon(obj.red);
        }

        if(evt.getKeyChar() == KeyEvent.VK_SPACE){
            obj.spin();
        }
    }

    @Override
    public void keyReleased(KeyEvent evt){

    }

    @Override
    public void keyTyped(KeyEvent evt){

    }
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    jLabel1 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    jPanel1.setPreferredSize(new java.awt.Dimension(350, 225));

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 350, Short.MAX_VALUE)
    );
    jPanel1Layout.setVerticalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGap(0, 338, Short.MAX_VALUE)
    );

    jLabel1.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
    jLabel1.setText("Nivel: " + String.valueOf(obj.level));

    jLabel2.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
    jLabel2.setText("Puntuacion: " + String.valueOf(obj.score));

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap(46, Short.MAX_VALUE)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(18, 18, 18)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addContainerGap(81, Short.MAX_VALUE)
            .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 338, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap())
        .addGroup(layout.createSequentialGroup()
            .addGap(118, 118, 118)
            .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(40, 40, 40)
            .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 34, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
    );

    pack();
}// </editor-fold>                        

public static void main(String args[]) {

    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
    * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
    */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(Game.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new Game().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JPanel jPanel1;
// End of variables declaration                   
} 

Library class:

package tetris;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class Library extends Thread{
JLabel tiles[][] = new JLabel[15][20];
ImageIcon red = new ImageIcon(getClass().getResource("redtile.png"));
ImageIcon white = new ImageIcon(getClass().getResource("whitetile.png"));
char figset = ' ';
int score = 0;
int level = 1;
int col1 = -1, col2 = -1, col3 = -1, col4 = -1, r1 = -1, r2 = -1, r3 = -1, r4 = -1;
int fallrate = 1500;

public void play(){
    Timer tm = new Timer();
    tm.start();
    boolean isPlaying = true;

    while(isPlaying){
        boolean isFalling = true;
        int tspinned = 0;
        setFigure();

        while(isFalling){
            try {
                Thread.sleep(fallrate);

                tiles[r1][col1].setIcon(white);
                tiles[r2][col2].setIcon(white);
                tiles[r3][col3].setIcon(white);
                tiles[r4][col4].setIcon(white);
                r1 += 1;
                r2 += 1;
                r3 += 1;
                r4 += 1;

                tiles[r1][col1].setIcon(red);
                tiles[r2][col2].setIcon(red);
                tiles[r3][col3].setIcon(red);
                tiles[r4][col4].setIcon(red);

                if((r1 == tiles.length-1 || r2 == tiles.length-1 || r3 == tiles.length-1 || r4 == tiles.length-1) ||
                        (tiles[r1+1][col1].getIcon() == red&&r1+1 != r2 && r1+1 != r3 && r1+1 != r4) || (tiles[r2+1][col2].getIcon() == red&&r2+1 != r1 && r2+1 != r3 && r2+1 != r4) ||
                        (tiles[r3+1][col3].getIcon() == red&&r3+1 != r2 && r3+1 != r1 && r3+1 != r4) || (tiles[r4+1][col4].getIcon() == red&&r4+1 != r2 && r4+1 != r3 && r4+1 != r1)){
                    isFalling = false;
                    checkwin(r1,r2,r3,r4);
                    if(r1+1 == 2 || r2+1 == 2 || r3+1 == 2 || r4+1 == 2){
                        isPlaying = false;
                    }
                }
            } catch (InterruptedException ex) {
                Logger.getLogger(Library.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }
    JOptionPane.showMessageDialog(null,"Ha perdido.\nPuntuación final: " + score);
    System.exit(0);
}

public void spin(){

}

public void setTiles(int row, int col, JLabel label){
    tiles[row][col] = label;
}

public void setFigure(){
    int choice = (int)(Math.random()*7)+1;      

    switch(choice){
        case 1: //I block
            for(int i = 0; i<4; i++){
                tiles[i][9].setIcon(red);
            }
            col1 = 9;
            col2 = 9;
            col3 = 9;
            col4 = 9;
            r1 = 0;
            r2 = 1;
            r3 = 2;
            r4 = 3;
            figset = 'I';
            break;
        case 2: //J block
            for(int i = 0; i<3; i++){
                tiles[i][9].setIcon(red);
            }
            tiles[2][8].setIcon(red);
            col1 = 9;
            col2 = 9;
            col3 = 9;
            col4 = 8;
            r1 = 0;
            r2 = 1;
            r3 = 2;
            r4 = 2;
            figset = 'J';
            break;
        case 3: //L block
            for(int i = 0; i<3; i++){
                tiles[i][9].setIcon(red);
            }
            tiles[2][10].setIcon(red);
            col1 = 9;
            col2 = 9;
            col3 = 9;
            col4 = 10;
            r1 = 0;
            r2 = 1;
            r3 = 2;
            r4 = 2;
            figset = 'L';
            break;
        case 4: //O block
            for(int i = 0; i<2; i++){
                for(int j = 8; j<10; j++){
                    tiles[i][j].setIcon(red);
                }
            }
            col1 = 9;
            col2 = 9;
            col3 = 10;
            col4 = 10;
            r1 = 0;
            r2 = 1;
            r3 = 0;
            r4 = 1;
            figset = 'O';
            break;
        case 5: //S block
            for(int i = 0; i<2; i++){
                tiles[i][9].setIcon(red);
            }
            tiles[0][10].setIcon(red);
            tiles[1][8].setIcon(red);
            col1 = 9;
            col2 = 9;
            col3 = 10;
            col4 = 8;
            r1 = 0;
            r2 = 1;
            r3 = 0;
            r4 = 1;
            figset = 'S';
            break;
        case 6: //Z block
            for(int i = 0; i<2; i++){
                tiles[i][9].setIcon(red);
            }
            tiles[0][8].setIcon(red);
            tiles[1][10].setIcon(red);
            col1 = 9;
            col2 = 9;
            col3 = 10;
            col4 = 8;
            r1 = 0;
            r2 = 1;
            r3 = 1;
            r4 = 0;
            figset = 'Z';
            break;
        case 7: //T block
            for(int i = 8; i<11; i++){
                tiles[0][i].setIcon(red);
            }
            tiles[1][9].setIcon(red);
            col1 = 8;
            col2 = 9;
            col3 = 10;
            col4 = 9;
            r1 = 0;
            r2 = 0;
            r3 = 0;
            r4 = 1;
            figset = 'T';
            break;
    }
}

public void checkwin(int one, int two, int three, int four){
    int c = 0;
    for(int i = 0; i<tiles[0].length; i++){
        if(tiles[one][i].getIcon() == red){
            c++;
        }
    }
    if(c == tiles[0].length){
        for(int i = 0; i<tiles[0].length; i++){
            tiles[one][i].setIcon(white);
        }
        score += 1000;

    }

    c = 0;
    for(int i = 0; i<tiles[0].length; i++){
        if(tiles[two][i].getIcon() == red){
            c++;
        }
    }
    if(c == tiles[0].length){
        for(int i = 0; i<tiles[0].length; i++){
            tiles[two][i].setIcon(white);
        }
        score += 1000;
    }


    c = 0;
    for(int i = 0; i<tiles[0].length; i++){
        if(tiles[three][i].getIcon() == red){
            c++;
        }
    }
    if(c == tiles[0].length){
        for(int i = 0; i<tiles[0].length; i++){
            tiles[three][i].setIcon(white);
        }
        score += 1000;
    }

    c = 0;
    for(int i = 0; i<tiles[0].length; i++){
        if(tiles[four][i].getIcon() == red){
            c++;
        }
    }
    if(c == tiles[0].length){
        for(int i = 0; i<tiles[0].length; i++){
            tiles[four][i].setIcon(white);
        }
        score += 1000;
    }
}

public void run(){
    play();
}
}
Was it helpful?

Solution

KeyListener will only respond to key events when the component they registered to has key board focus AND is focusable.

JLabel is not focusable by default.

Now, there are things you can "try" to make this work, or you could just use the a Key Bindings API which was designed to fix these issues

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top