Welcome to the Java Programming Forums


The professional, friendly Java community. 21,500 members and growing!


The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.


>> REGISTER NOW TO START POSTING


Members have full access to the forums. Advertisements are removed for registered users.

Results 1 to 2 of 2

Thread: JPanel not reacting to Keystrokes

  1. #1
    Junior Member
    Join Date
    Sep 2011
    Posts
    21
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Default JPanel not reacting to Keystrokes

    I'm working on a tetris game and I've been trying to get the keystroke actions to work; i've done it before in other applications but for some reason my jpanel is not calling any of the key methods when i hit a key. I don't know if this is a problem with the focus, whether I left out some needed code, or something else altogether... please help!

    The only code i need help on is PlayPanel (and possibly MainFrame) but I provided all my code for those who wish to compile and run it

    EDIT: I have also been looking at KeyBindings, does anyone know if that would help in a situation like this?

    MainFrame:
    package Tetris;
     
    import java.awt.*;
    import javax.swing.*;
     
    @SuppressWarnings({ "serial" })
    public class MainFrame extends JFrame {
    	public MainFrame() {
    		super("Tetris");
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setResizable(false);
    		JPanel optionInfo = new JPanel();
    		optionInfo.setLayout(new BoxLayout(optionInfo, BoxLayout.Y_AXIS));
    		optionInfo.setBackground(Color.BLACK);
    		PlayPanel play = new PlayPanel();
    		InfoPanel info = new InfoPanel(play);
    		OptionPanel options = new OptionPanel(info, play);
    		optionInfo.add(options);
    		optionInfo.add(info);
    		add(play, BorderLayout.CENTER);
    		add(optionInfo, BorderLayout.EAST);
    		pack();
    		setVisible(true);
    	}
    	public static void main(String[] args) {
    		new MainFrame();
    	}
    }

    PlayPanel:
    package Tetris;
     
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.border.Border;
    import java.util.TimerTask;
    import java.util.Timer;
     
    @SuppressWarnings({ "serial", "unused" })
    public class PlayPanel extends JPanel implements KeyListener {
    	private Tetromino tet;
    	private Timer dropTimer;
    	private Timer colorTimer;
    	private JButton[][] buttonAt;
    	private boolean[][] isDeadButtonAt;
    	private int linesCleared = 0;
    	private int dropSpeed = 1000;
     
    	public PlayPanel() {
    		super();
    		setBackground(Color.BLACK);
    		GridLayout grid = new GridLayout(18, 10); //rows, columns
    		setLayout(grid);
    		buttonAt = new JButton[10][18];
    		isDeadButtonAt = new boolean[10][18];
    		for(int y = 0; y < 18; y++) {
    			for(int x = 0; x < 10; x++) {
    				buttonAt[x][y] = new JButton();
    				buttonAt[x][y].setEnabled(false);
    				buttonAt[x][y].setPreferredSize(new Dimension(30, 30));
    				buttonAt[x][y].setOpaque(false); //false makes background visible
    				add(buttonAt[x][y]);
    			}
    		}
    		setFocusable(true);
    		addKeyListener(this);
    		setVisible(true);
    	}
    	public void newGame() {
    		if(!(dropTimer == null)) { dropTimer.cancel(); }
    		if(!(colorTimer == null)) { colorTimer.cancel(); }
    		for(int x = 0; x < 10; x++) {
    			for(int y = 0; y < 18; y++) {
    				buttonAt[x][y].setBackground(null);
    				buttonAt[x][y].setOpaque(false);
    				isDeadButtonAt[x][y] = false;
    			}
    		}
    		dropSpeed = 1000;
    		dropTimer  = new Timer();
    		dropTimer.schedule(new DropTimer(), dropSpeed, dropSpeed);
    		colorTimer = new Timer();
    		colorTimer.schedule(new ColorTimer(), 0, 100);
    		tet = new Tetromino();
    	}
    	public void moveTet(boolean rotated) {
    		int[] x = new int[4];	int lastX[] = new int[4];
    		int[] y = new int[4];	int lastY[] = new int[4];
    		int dropLevel = tet.getDropLevel();
    		int lastDropLevel = tet.getLastDropLevel();
    		int rotation = tet.getRotation();
    		int height = tet.getHeight();
    		int movedPos = tet.getMovedPos();
    		if(movedPos < 0 || movedPos > 9) { return; }
    		for(int i = 0; i < 4; i++) {
    			x[i] = tet.getPosX()[rotation][i] + movedPos;
    			y[i] = tet.getPosY()[rotation][i] + dropLevel;
    			lastX[i] = tet.getLastPosX()[i] + movedPos;
    			lastY[i] = tet.getLastPosY()[i] + lastDropLevel;
    			if(dropLevel + height > 18 || isDeadButtonAt[x[i]][y[i]]) {
    				if(rotated == true) { return; }
    				movedPos = 0;
    				setDeadButtons();
    				tet = new Tetromino();
    				return;
    			}
    		}
    		for(int i = 0; i < 4; i++) {
    			buttonAt[lastX[i]][lastY[i]].setOpaque(false);
    			buttonAt[lastX[i]][lastY[i]].setBackground(null);
    		}
    		for(int i = 0; i < 4; i++) {
    			buttonAt[x[i]][y[i]].setOpaque(true);
    			buttonAt[x[i]][y[i]].setBackground(tet.getNewColor());	
    		}
    		tet.setLastPos(tet.getPosX()[rotation], tet.getPosY()[rotation]);
    		if(rotated == false) {
    			tet.setLastDropLevel(dropLevel);
    			tet.setDropLevel(dropLevel + 1);
    		}
    	}
    	public void setDeadButtons() {
    		for(int x = 0; x < 10; x++) {
    			for(int y = 0; y < 18; y++) {
    				if(buttonAt[x][y].isOpaque()) { isDeadButtonAt[x][y] = true; }
    				else { isDeadButtonAt[x][y] = false; }
    			}
    		}
    	}
    	public void keyTyped(KeyEvent e) { }
    	public void keyReleased(KeyEvent e) { }
    	public void keyPressed(KeyEvent e) {
    		System.out.println("KEY PRESSED");
    		switch(e.getKeyCode()) {
    		case KeyEvent.VK_UP:
    			System.out.println("UP PRESSED");
    			tet.rotate();
    			moveTet(true);
    			break;
    		case KeyEvent.VK_LEFT:
    			System.out.println("LEFT PRESSED");
    			tet.setMovedPos(tet.getMovedPos() - 1);
    			moveTet(false);
    			break;
    		}
    	}
    	public void pause() {
    		dropTimer.cancel();
    		//colorTimer.cancel();
    	}
    	public void resume() {
    		dropTimer = new Timer();
    		//colorTimer = new Timer();
    		dropTimer.schedule(new DropTimer(), dropSpeed, dropSpeed);
    		//colorTimer.schedule(new ColorTimer(), 0, 100);
    	}
    	public class DropTimer extends TimerTask implements Runnable {
    		public void run() {
    			moveTet(false);
    		}
    	}
    	public class ColorTimer extends TimerTask implements Runnable {
    		public void run() {
    			for(int x = 0; x < 10; x++) {
    				for(int y = 0; y < 18; y++) {
    					if(buttonAt[x][y].isOpaque()) {
    						buttonAt[x][y].setBackground(tet.getNewColor());
    					}
    				}
    			}
    		}
    	}
    	public int getLinesCleared() {
    		return linesCleared;
    	}
    	public void resetLinesCleared() {
    		linesCleared = 0;
    	}
    	public void updateLinesCleared() {
     
    	}
    }

    Tetromino:
    package Tetris;
     
    import java.util.Random;
    import java.awt.Color;
     
    public class Tetromino {
    	private int type;
    	private Color tetColor;
    	private int[] lastPosX = new int[]{0, 0, 0, 0};
    	private int[] lastPosY = new int[]{0, 0, 0, 0};
    	private int[][] posX = new int[4][4];
    	private int[][] posY = new int[4][4];
    	private int height;
    	private int movedPos = 5; //middle of grid layout
    	private int dropLevel = 0;
    	private int lastDropLevel = 0;
    	private int rotation = 0;
    	private int lastRotation = -1;
     
    	public Tetromino() {
    		Random genNum = new Random();
    		type = genNum.nextInt(7);
    		switch(type) {
    		case 0: buildIBlock(); break;
    		case 1: buildOBlock(); break;
    		case 2: buildTBlock(); break;
    		case 3: buildLBlock(); break;
    		case 4: buildJBlock(); break;
    		case 5: buildSBlock(); break;
    		case 6: buildZBlock(); break;
    		} 
    		if(type == 0) { height = 1;	}
    		else { height = 2; }
    		tetColor = getNewColor();
    	}
    	public Color getNewColor() {
    		Color newColor = null;
    		Random genNum = new Random();
    		int colorType = genNum.nextInt(7);
    		switch(colorType) {
    		case 0: newColor = Color.BLUE; break;
    		case 1: newColor = Color.CYAN; break;
    		case 2: newColor = Color.GREEN; break;
    		case 3: newColor = Color.MAGENTA; break;
    		case 4: newColor = Color.ORANGE; break;
    		case 5: newColor = Color.RED; break;
    		case 6: newColor = Color.WHITE; break;
    		}
    		if(newColor.equals(tetColor)) { getNewColor(); }
    		return newColor;
    	}
    	public void buildIBlock() {
    		for(int i = 0; i < 4; i++) {
    			if(i%2 == 0) {
    				posX[i] = new int[] {-2, -1, 0, 1};		posY[i] = new int[] {0, 0, 0, 0};
    			}
    			else {
    				posX[i] = new int[] {0, 0, 0, 0};		posY[i] = new int[] {0, 1, 2, 3};
    			}
    		}
    	}	
    	public void buildOBlock() {
    		for(int i = 0; i < 4; i++) {
    			posX[i] = new int[] {-1, 0, -1, 0};		posY[i] = new int[] {0, 0, 1, 1};
    		}
    	}
    	public void buildTBlock() {
    		posX[0] = new int[] {-1, 0, 1, 0};		posY[0] = new int[] {0, 0, 0, 1};
    		posX[1] = new int[] {0, -1, 0, 0};		posY[1] = new int[] {0, 1, 1, 2};
    		posX[2] = new int[] {0, -1, 0, 1};		posY[2] = new int[] {0, 1, 1, 1};
    		posX[3] = new int[] {-1, -1, 0, -1};	posY[3] = new int[] {0, 1, 1, 2};
    	}
    	public void buildLBlock() {
    		posX[0] = new int[] {-1, 0, 1, -1};		posY[0] = new int[] {0, 0, 0, 1};
    		posX[1] = new int[] {-1, 0, 0, 0}; 		posY[1] = new int[] {0, 0, 1, 2};
    		posX[2] = new int[] {1, -1, 0, 1};		posY[2] = new int[] {0, 1, 1, 1};
    		posX[3] = new int[] {-1, -1, -1, 0};	posY[3] = new int[] {0, 1, 2, 2};
    	}	
    	public void buildJBlock() {
    		posX[0] = new int[] {-1, 0, 1, 1};		posY[0] = new int[] {0, 0, 0, 1};
    		posX[1] = new int[] {0, 0, -1, 0};		posY[1] = new int[] {0, 1, 2, 2};
    		posX[2] = new int[] {-1, -1, 0, 1};		posY[2] = new int[] {0, 1, 1, 1};
    		posX[3] = new int[] {-1, 0, -1, -1};	posY[3] = new int[] {0, 0, 1, 2};
    	}	
    	public void buildSBlock() {
    		for(int i = 0; i < 4; i++) {
    			if(i%2 == 0) {
    				posX[i] = new int[] {0, 1, -1, 0};		posY[i] = new int[] {0, 0, 1, 1};
    			} else {
    				posX[i] = new int[] {-1, -1, 0, 0};		posY[i] = new int[] {0, 1, 1, 2};
    			}
    		}
    	}
    	public void buildZBlock() {
    		for(int i = 0; i < 4; i++) {
    			if(i%2 == 0) {
    				posX[i] = new int[] {-1, 0, 0, 1};		posY[i] = new int[] {0, 0, 1, 1};
    			} else {
    				posX[i] = new int[] {0, 0, -1, -1};		posY[i] = new int[] {0, 1, 1, 2};
    			}
    		}
    	}
    	public void rotate() {
    		lastRotation = rotation;
    		rotation = (rotation+1)%4;
    		switch(type) {
    		case 0: if(rotation % 2 == 0) { height = 1; } else { height = 4; } break;
    		case 1: height = 2; break;
    		default: if(rotation % 2 == 0) { height = 2; } else { height = 3; } break;
    		}
    	}
    	public void setLastPos(int[] posX, int[] posY) {
    		lastPosX = posX;	lastPosY = posY;
    	}
    	public void resetLastPos() {
    		lastPosX = new int[] {0,0,0,0};
    		lastPosY = new int[] {0,0,0,0};
    		lastDropLevel = 0;
    	}
    	public int getType() { return type; }
    	public int[] getLastPosX() { return lastPosX; }
    	public int[] getLastPosY() { return lastPosY; }
    	public int[][] getPosX() { return posX; }
    	public int[][] getPosY() { return posY; }
    	public int getHeight() { return height; }
    	public int getMovedPos() { return movedPos; }
    	public int getDropLevel() { return dropLevel; }
    	public int getLastDropLevel() { return lastDropLevel; }
    	public int getLastRotation() { return lastRotation; }
    	public int getRotation() { return rotation; }
    	public Color getTetColor() { return tetColor; }
    	public void setMovedPos(int m) { movedPos = m; }
    	public void setDropLevel(int d) { dropLevel = d; }
    	public void setLastDropLevel(int l) { lastDropLevel = l; }
    }

    InfoPanel:
    package Tetris;
     
    import java.awt.*;
     
    import javax.swing.*;
     
    @SuppressWarnings({ "serial" })
    public class InfoPanel extends JPanel  {
    	private ScoreTracker scoreTracker;
    	private PlayPanel playPanel;
    	private JLabel score = new JLabel();
    	private JLabel level = new JLabel();
    	private JLabel linesCleared = new JLabel();
     
    	public InfoPanel(PlayPanel play) {
    		playPanel = play;
    		scoreTracker = new ScoreTracker();
    		setOpaque(false);
    		setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
    		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    		JLabel scoreLabel = new JLabel("SCORE");
    		JLabel levelLabel = new JLabel("LEVEL");
    		JLabel linesLabel = new JLabel("LINES");
    		JLabel clearedLabel = new JLabel("CLEARED");
    		scoreLabel.setForeground(Color.WHITE);
    		levelLabel.setForeground(Color.WHITE);
    		linesLabel.setForeground(Color.WHITE);
    		clearedLabel.setForeground(Color.WHITE);
    		score.setForeground(Color.WHITE);
    		level.setForeground(Color.WHITE);
    		linesCleared.setForeground(Color.WHITE);
    		scoreLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
    		levelLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
    		linesLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
    		clearedLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
    		score.setAlignmentX(Component.CENTER_ALIGNMENT);
    		level.setAlignmentX(Component.CENTER_ALIGNMENT);
    		linesCleared.setAlignmentX(Component.CENTER_ALIGNMENT);
    		add(scoreLabel);
    		add(score);
    		add(levelLabel);
    		add(level);
    		add(linesLabel);
    		add(clearedLabel);
    		add(linesCleared);
    		setVisible(true);	
    	}
    	public void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		score.setText("" + scoreTracker.getScore());
    		level.setText("" + (1 + Integer.parseInt(score.getText())/1000));
    		linesCleared.setText("" + playPanel.getLinesCleared());
    	}
    	public void updateInfo() {
    		if(scoreTracker == null) scoreTracker = new ScoreTracker();
    		else scoreTracker.updateScore();
    		repaint();
    	}
    	public void resetInfo() {
    		scoreTracker.resetScore();
    		playPanel.resetLinesCleared();
    		repaint();
    	}
    }

    OptionPanel:
    package Tetris;
     
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.border.*;
     
    @SuppressWarnings({ "serial", "unused" })
    public class OptionPanel extends JPanel implements ActionListener {
    	private InfoPanel infoPanel;
    	private PlayPanel playPanel;
    	private JButton newGame = new JButton("NEW GAME");
    	private JButton pause = new JButton("PAUSE");
    	private JButton quit = new JButton("QUIT");
    	private JButton addScore = new JButton("+100");
    	private Font f = new Font("SERIF", 0, 14);
    	private boolean isPaused;
     
     
    	public OptionPanel(InfoPanel info, PlayPanel play) {
    		infoPanel = info;
    		playPanel = play;
    		setOpaque(false);
    		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
    		setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    		newGame.addActionListener(this);
    		pause.addActionListener(this);
    		quit.addActionListener(this);
    		addScore.addActionListener(this);
    		newGame.setFont(f);
    		newGame.setForeground(Color.GREEN);
    		newGame.setBackground(Color.BLACK);
    		newGame.setBorder(null);
    		newGame.setAlignmentX(Component.CENTER_ALIGNMENT);
    		pause.setFont(f);
    		pause.setForeground(Color.ORANGE);
    		pause.setBackground(Color.BLACK);
    		pause.setBorder(null);
    		pause.setAlignmentX(Component.CENTER_ALIGNMENT);
    		quit.setFont(f);
    		quit.setForeground(Color.RED);
    		quit.setBackground(Color.BLACK);
    		quit.setBorder(null);
    		quit.setAlignmentX(Component.CENTER_ALIGNMENT);
    		add(newGame);
    		add(pause);
    		add(quit);
    		setVisible(true);
    	}
    	public void actionPerformed(ActionEvent event) {
    		Object source = event.getSource();
    		if(source.equals(newGame)) {
    			pause.setText("PAUSE");
    			infoPanel.resetInfo();
    			playPanel.newGame();
    		}
    		if(source.equals(pause)) {
    			if(pause.getText().equals("PAUSE")) { 
    				pause.setText("RESUME");
    				playPanel.pause();
    				}
    			else { 
    				pause.setText("PAUSE"); 
    				playPanel.resume();
    			}
    		}
    		if(source.equals(quit)) {
    			System.exit(0);
    		}
    		if(source.equals(addScore)) {
    			infoPanel.updateInfo();
    		}
    	}
    }

    ScoreTracker (necessary to compile but I haven't fleshed out the methods yet)
    package Tetris;
     
    public class ScoreTracker {
    	private int score;
     
    	public ScoreTracker() {
    		score = 0;
    	}	
    	public void updateScore() {
    		score += 100;
    	}	
    	public void resetScore() {
    		score = 0;
    	}	
    	public int getScore() {
    		return score;
    	}
    }


  2. #2
    Super Moderator curmudgeon's Avatar
    Join Date
    Aug 2012
    Posts
    1,130
    My Mood
    Cynical
    Thanks
    64
    Thanked 139 Times in 134 Posts

    Default Re: JPanel not reacting to Keystrokes

    Quote Originally Posted by sonicjr View Post
    I'm working on a tetris game and I've been trying to get the keystroke actions to work; i've done it before in other applications but for some reason my jpanel is not calling any of the key methods when i hit a key. I don't know if this is a problem with the focus, whether I left out some needed code, or something else altogether... please help!
    Usually yes, this is a problem of focus.

    The only code i need help on is PlayPanel (and possibly MainFrame) but I provided all my code for those who wish to compile and run it

    EDIT: I have also been looking at KeyBindings, does anyone know if that would help in a situation like this?
    And yes, Key Bindings will usually solve this issue. Regardless, you are encouraged to use Key Bindings in place of KeyListeners as a general rule since the latter are felt to be a much lower-level construct.

    Addendum: don't use a java.util.Timer with Swing GUI's, especially for code that needs to be called on the event thread. This is what javax.swing.Timer's are for. Use them instead.

    Addendum 2: For a small taste of Key Binding, change your PlayPanel constructor to something like:

       public PlayPanel() {
          super();
          setBackground(Color.BLACK);
          GridLayout grid = new GridLayout(18, 10); // rows, columns
          setLayout(grid);
          buttonAt = new JButton[10][18];
          isDeadButtonAt = new boolean[10][18];
          for (int y = 0; y < 18; y++) {
             for (int x = 0; x < 10; x++) {
                buttonAt[x][y] = new JButton();
                buttonAt[x][y].setEnabled(false);
                buttonAt[x][y].setPreferredSize(new Dimension(30, 30));
                buttonAt[x][y].setOpaque(false); // false makes background visible
                add(buttonAt[x][y]);
             }
          }
          setFocusable(true);
          // addKeyListener(this); // you don't need this
          // setVisible(true); // you rarely need this in a non-top level window
     
          ActionMap actionMap = getActionMap();
          int condition = WHEN_IN_FOCUSED_WINDOW;
          InputMap inputMap = getInputMap(condition);
     
          String upKey  = "up key";
          inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), upKey);
          actionMap.put(upKey, new AbstractAction() {
     
             @Override
             public void actionPerformed(ActionEvent aEvt) {
                System.out.println("up key pressed");
             }
          });
       }

  3. The Following User Says Thank You to curmudgeon For This Useful Post:

    sonicjr (November 18th, 2012)

Similar Threads

  1. JPanel
    By Daigan in forum AWT / Java Swing
    Replies: 25
    Last Post: January 17th, 2012, 09:48 AM
  2. [SOLVED] Pesky <JPanel>.getWidth() and <JPanel>.getHeight() Methods...
    By snowguy13 in forum AWT / Java Swing
    Replies: 1
    Last Post: December 31st, 2011, 03:35 PM
  3. Regarding Keystrokes
    By esplanade56 in forum Java Theory & Questions
    Replies: 12
    Last Post: May 25th, 2011, 07:46 AM
  4. How to copy image from one jpanel to another jpanel
    By ramanavarayuri1986 in forum AWT / Java Swing
    Replies: 0
    Last Post: February 15th, 2010, 02:36 AM
  5. Creating and displaying a JPanel inside another JPanel
    By JayDuck in forum AWT / Java Swing
    Replies: 1
    Last Post: April 7th, 2009, 09:02 AM