Question

i have been trying this code and editing it but it doesnt work. it is suppose to get a keyboard input store it in the variable "c" and then compare that to keys on the keyboard. Then it is suppose to move a little square depending the key pressed. The keyboard doesnt seem to be recognised. Can someone please help me? Please be aware i am 14 so please dont say how simple and easy it is, i am still learning and could you also write it in a way i am likely to understand. Thank you in advance

'package package1;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Class1 extends JPanel implements KeyListener, ActionListener{

Timer timer = new Timer(5, this);

//variables    
int cox = 0;
int spx = 0;  //cox = coordinates x, spx = speedx
int coy = 0;
int spy = 0;  //coy = coordinates y, spy = speedy

public void paintComponent(Graphics g)
{
    timer.start();

    super.paintComponent(g);
    g.setColor(Color.BLUE);     
    g.fillRect(cox, coy, 50, 50);

    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
}

public void actionPerformed(ActionEvent e)
{
    cox = cox + spx;
    coy = coy + spy;
    repaint();
}

public void keyPressed(KeyEvent e)
{
    int c = e.getKeyCode();

    if(c == KeyEvent.VK_LEFT)
    {
        spx = -1;
        spy = 0;
    }
    if(c == KeyEvent.VK_UP)
    {
        spx = 0;
        spy = -1;
    }
    if(c == KeyEvent.VK_RIGHT)
    {
        spx = 1;
        spy = 0;
    }
    if(c == KeyEvent.VK_DOWN)
    {
        spx = 0;
        spy = 1;
    }

}

public void keyTyped(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
    spx = 0;
    spy = 0;
}

public static void main(String args[])
{
    Class1 t = new Class1();
    JFrame frame = new JFrame("window");
    frame.setSize(500,500);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(t);
}
}
Was it helpful?

Solution

Problems with your code:

  • KeyListeners are very low-level constructs, and in general should be avoided in favor of key bindings in most Swing applications. Doing this will also make it much easier to solve focus issues that plague KeyListeners, and which is causing your current KeyListener to do nothing whatsoever. If you read most questions on this site tagged with Swing and KeyListeners, you'll see this advice time and again -- because it's true, and it works.
  • Please understand that the paintComponent(Graphics g) method is for painting only. It is frequently called, often out of your control, since the OS can induce it to be called.
  • The paintComponent method has a significant influence on the perceived responsiveness of your GUI, since it is in control of drawing your GUI and any animations that your GUI might contain. If it is slowed for any reason, your GUI will seem slow.
  • For this reason, this method should be used for drawing and only drawing and nothing but drawing. Specifically,
    • Don't start your Swing Timer from within this method,
    • Don't add KeyListeners from within this method (unless you want to add a KeyListener 20 times to the GUI which will result in wildly unpredictable behavior),
    • Don't change the state of any of your objects from within this method.

For example:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

import javax.swing.*;

@SuppressWarnings("serial")
public class Class1B extends JPanel {   
   private static final int PREF_W = 500;
   private static final int PREF_H = PREF_W;
   private static final int ANIMATION_DELAY = 15;
   private static final int RECT_WIDTH = 15;
   private static final Color RECT_COLOR = Color.red;
   private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
   private Map<Integer, Direction> keyToDir = new HashMap<>();
   private Timer animationTimer;
   public int rectX;
   public int rectY;


   public Class1B() {
      for (Direction dir : Direction.values()) {
         dirMap.put(dir, Boolean.FALSE);
      }
      keyToDir.put(KeyEvent.VK_UP, Direction.UP);
      keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
      keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
      keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
      setKeyBindings();

      animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
      animationTimer.start();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(RECT_COLOR);
      g.fillRect(rectX, rectY, RECT_WIDTH, RECT_WIDTH);
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      final InputMap inputMap = getInputMap(condition);
      final ActionMap actionMap = getActionMap();
      boolean[] keyPressed = { true, false };
      for (Integer keyCode : keyToDir.keySet()) {
         Direction dir = keyToDir.get(keyCode);
         for (boolean onKeyPress : keyPressed) {
            boolean onKeyRelease = !onKeyPress;
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
                  onKeyRelease);
            Object key = keyStroke.toString();
            inputMap.put(keyStroke, key);
            actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
         }
      }
   }

   private class KeyBindingsAction extends AbstractAction {
      private Direction dir;
      boolean pressed;

      public KeyBindingsAction(Direction dir, boolean pressed) {
         this.dir = dir;
         this.pressed = pressed;
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         dirMap.put(dir, pressed);
      }
   }

   private class AnimationListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent evt) {
         boolean repaint = false;
         for (Direction dir : Direction.values()) {
            if (dirMap.get(dir)) {
               rectX += dir.getIncrX();
               rectY += dir.getIncrY();
               repaint = true;
            }
         }
         if (repaint) {
            repaint();
         }
      }
   }

   private static void createAndShowGui() {
      Class1B mainPanel = new Class1B();

      JFrame frame = new JFrame("Class1B");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

enum Direction {
   UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
   private int incrX;
   private int incrY;

   private Direction(int incrX, int incrY) {
      this.incrX = incrX;
      this.incrY = incrY;
   }

   public int getIncrX() {
      return incrX;
   }

   public int getIncrY() {
      return incrY;
   }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top