0

i want my rectangle to stop when the user press both left and right key. I researched about multiple key handlings but couldnt manage to find anything.

package View;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class GamePanel extends JPanel {

private final int WIDTH = 600, HEIGHT = 500;

// PROPERTIES

private Timer timer;
int x = 0;
int y = 475;
int velX = 0; // only left or right

// CONSTRUCTOR

public GamePanel() {

    setSize(WIDTH, HEIGHT);
    setBackground(new Color(240, 255, 255));

    timer = new Timer(5, new MyTimerListener());        
    addKeyListener( new MyKeyListener());

    setFocusable(true); // for key listening
    setFocusTraversalKeysEnabled(false); 

    timer.start();
}

// METHODS

@Override 
public void paintComponent(Graphics g) {

    super.paintComponent(g);
    g.setColor( new Color(201, 51, 51));
    g.fillRoundRect(x, y, 80, 20, 15, 15);      
}

public class MyTimerListener implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {

        if ( x < 0 )
        {
            velX = 0;
            x = 0;          
        }

        if ( x > 520 )
        {
            velX = 0;
            x = 520;
        }

        x = x + velX;

        repaint();
    }       
}

public class MyKeyListener implements KeyListener {

    @Override
    public void keyPressed(KeyEvent e) {

        int code = e.getKeyCode();

        if ( code == KeyEvent.VK_LEFT )
            velX = -1;

        if ( code == KeyEvent.VK_RIGHT )
            velX = 1;       
    }
    @Override
    public void keyReleased(KeyEvent e) {

        velX = 0;           
    }
    @Override
    public void keyTyped(KeyEvent e) {}             
}   
}

thanks for heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeelp

a busy cat ![two muppets]

mKorbel
  • 109,525
  • 20
  • 134
  • 319
funky-nd
  • 637
  • 1
  • 9
  • 25
  • 1
    Pet peeve, I hate, `"I researched about multiple key handlings but couldnt manage to find anything."` Hate, hate hate it. Surely you've read about key bindings, no? Shoot, I've written several code examples on this site that address this very issue -- please search again. – Hovercraft Full Of Eels Jul 03 '15 at 01:53
  • 2
    [For example](http://stackoverflow.com/a/6887354/522444) and [another example](http://stackoverflow.com/a/12545773/522444). – Hovercraft Full Of Eels Jul 03 '15 at 01:55
  • so u mean I dont need key listener. i am trying to understand that now – funky-nd Jul 03 '15 at 01:58
  • 2
    No, I'm saying that you shouldn't use a Key Listener. If this is a Swing application, then you should use Key Bindings. Even Oracle will tell you this. – Hovercraft Full Of Eels Jul 03 '15 at 02:00
  • when i watched youtube videos about moving graphics objects i thought it should gonna be key listener. sorry, didnt heard about keystrokes. – funky-nd Jul 03 '15 at 02:01
  • 2
    Please do a more thorough search before stating that you did research on a subject. A simple search on this site on the topic of keyboard and Swing would lead you easily to know what key bindings are and that they are usually preferred to KeyListeners. – Hovercraft Full Of Eels Jul 03 '15 at 02:03
  • 3
    For [example](http://stackoverflow.com/a/14001011/230513). – trashgod Jul 03 '15 at 02:16
  • 1
    1- `KeyListener` is to limited; 2- You shouldn't be changing the state when the key is pressed, as when keys are held down, they repeat, instead, you should have a "pressed" and "released" handler which changes a state of a flag indicating which keys are pressed. You could then use a "main-loop" to update the state based on which flags are set, this provides infinite more control. There is also a limit to the number of keys you can press simultanously – MadProgrammer Jul 03 '15 at 02:22
  • thanks. these are alll nice. i will examine the ones that i liked deeply. there are things that i dont know. – funky-nd Jul 03 '15 at 02:22
  • 2
    For [example](http://stackoverflow.com/questions/20672834/how-can-i-make-multiple-key-bindings-work-at-the-same-time/20672914#20672914) and [example](http://stackoverflow.com/questions/13528953/detecting-multiple-keypresses-in-java/13537419#13537419) and [example](http://stackoverflow.com/questions/28423393/how-to-get-a-rectangle-to-stop-when-you-release-a-key-that-moves-it/28423725#28423725) – MadProgrammer Jul 03 '15 at 02:26

1 Answers1

3

So again, use Key Bindings and not a KeyListener. You would want to use separate bindings for key press and release for both right and left arrow keys, and will want to have your key binding actions change the state of your program that will effect how the Swing Timer moves the paddle. In this example here (borrowed from another example of mine), I've created an enum, Direction to encapsulate the right and left directions, and have created a Map<Direction, Boolean> that will associate a boolean with both right and left directions. A right arrow key press will change the map to associate the RIGHT direction with a true boolean, and key release would do the opposite. The Timer would poll the Map to see where to move the paddle. For example:

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

import javax.swing.*;

@SuppressWarnings("serial")
public class GamePanel2 extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 500;
   private static final int PADDLE_Y = 475;
   private static final int PADDLE_W = 80;
   private static final int PADDLE_H = 20;
   private static final int PADDLE_ARC = 15;
   private static final int TIME_DELAY = 15;
   public static final int VEL_X = 2;
   private static final Color PADDLE_COLOR = new Color(201, 51, 51);
   private int paddleX;
   private Timer time = new Timer(TIME_DELAY, new TimerListener());

   // key presses and releases will change the boolean values held in this Map
   // When an arrow key is pressed, the direction-corresponding boolean is set true
   // and likewise when the arrow key is released the direction corresponding boolean is false
   private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);


   public GamePanel2() {
      setKeyBindings();
      time.start();
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      // iterate through all the Direction enums
      for (Direction direction : Direction.values()) {
         // set all values to false
         dirMap.put(direction, false);

         // create two key strokes, one for pressed and one for released
         int keyValue = direction.getKeyValue();
         KeyStroke pressedKey = KeyStroke.getKeyStroke(keyValue, 0, false);
         KeyStroke releasedKey = KeyStroke.getKeyStroke(keyValue, 0, true);

         // create two Actions, one for pressed, one for released
         Action pressedAction = new KeyAction(direction, true);
         Action releasedAction = new KeyAction(direction, false);

         // add keystroke to inputMap and use keystroke's toString as binding link
         inputMap.put(pressedKey, pressedKey.toString());
         inputMap.put(releasedKey, releasedKey.toString());

         // link binding links to our actions
         actionMap.put(pressedKey.toString(), pressedAction);
         actionMap.put(releasedKey.toString(), releasedAction);
      }

   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g.setColor(PADDLE_COLOR);
      g.fillRoundRect(paddleX, PADDLE_Y, PADDLE_W, PADDLE_H, PADDLE_ARC, PADDLE_ARC);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         // if JPanel no longer displayed, stop the Timer
         if (!GamePanel2.this.isDisplayable()) {
            ((Timer) e.getSource()).stop();
         }
         // here's the key: iterate through the Direction enum
         for (Direction direction : Direction.values()) {
            // get corresponding boolean from dirMap
            // and if true, change location of x and y
            if (dirMap.get(direction)) {
               int possibleX = paddleX + VEL_X * direction.getDeltaX();
               if (direction == direction.RIGHT && possibleX + PADDLE_W <= getWidth()) {
                  paddleX = possibleX;
               }
               if (direction == Direction.LEFT && possibleX >= 0) {
                  paddleX = possibleX;
               }
            }
         }
         repaint();
      }
   }

   private class KeyAction extends AbstractAction {
      private Direction direction;
      private boolean pressed;

      public KeyAction(Direction direction, boolean pressed) {
         this.direction = direction;
         this.pressed = pressed;               
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         dirMap.put(direction, pressed); // key press simply changes the map, that's it.
      }
   }

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

      JFrame frame = new JFrame("GamePanel2");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_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 {
   LEFT("Left", KeyEvent.VK_LEFT, -1),
   RIGHT("Right", KeyEvent.VK_RIGHT, 1);

   private String text; 
   private int keyValue; // KeyEvent.VK_?
   private int deltaX; 

   Direction(String text, int keyValue, int deltaX) {
      this.text = text;
      this.keyValue = keyValue;
      this.deltaX = deltaX;
   }

   public String getText() {
      return text;
   }

   public int getKeyValue() {
      return keyValue;
   }

   @Override
   public String toString() {
      return text;
   }

   public int getDeltaX() {
      return deltaX;
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373