# Solution for repeating keyPressed while holding key

**URL:** <https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989>\
**Category:** Coding Questions\
**Created:** [September 30, 2018, 8:21pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989 "2018-09-30T20:21:49Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![tutantontut](https://avatars.discourse-cdn.com/v4/letter/t/ed8c4c/32.png) [@tutantontut](https://discourse.processing.org/u/tutantontut)\
**Post date:** [September 30, 2018, 8:21pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/1 "2018-09-30T20:21:49Z")

</div>

I came up with a solution for a problem I’ve encountered regarding inputs.

The problem:  
When you hold down a key, at least on my computer it registers as if you were repeatedly pressing that key very fast. In some cases you only want to get one single registered keypress, even if the key is held down.

Just to clarify my point with a stupid example: say you were creating a game, and the goal of the game is to press a single key repeatedly, as fast as possible:

```auto
int totalPresses = 0;
void setup(){}
void draw(){}

void keyPressed(){
  if (key == 'a') {
    totalPresses += 1;
  }
}

```

Being able to hold down ‘a’ would ruin the challenge and the game.

The solution:

```auto
boolean okay = true; //Create a boolean
totalPresses = 0;

void setup(){}
void draw(){}

void keyPressed(){
  if (okay && key == 'a') { //Check if boolean is true
    totalPresses += 1; //Do whatever (jump, move, call functions etc...)
    okay = false; //Set boolean to false
  }
}

void keyReleased() {
  okay = true; //Only when the key is released the boolean is set to true again
}

```

That’s pretty much it.  
My reason for posting this is I couldn’t find any solution anywhere no matter where I searched. I’m hoping this will prevent other newbies from that misery 😛

---

<div class="post-metadata">

**Author:** ![TheWizardBear](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/thewizardbear/32/3552_2.png) [@TheWizardBear](https://discourse.processing.org/u/TheWizardBear)\
**Post date:** [October 1, 2018, 5:56pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/2 "2018-10-01T17:56:31Z")

</div>

Another solution is to simply use keyReleased(). Although, of course, this is only called when the player lets go of the key, this means that the player cannot simply hold down the key.

```auto
int totalPresses = 0;

void setup(){}

void draw(){}

void keyReleased(){ //Called when the player lets go of the key.
  if (key == 'a') {
    totalPresses += 1;
  }
}

```

It is simpler to impliment though it might not be the right solution if you need the counter to go up only when they press the key.

---

<div class="post-metadata">

**Author:** ![tutantontut](https://avatars.discourse-cdn.com/v4/letter/t/ed8c4c/32.png) [@tutantontut](https://discourse.processing.org/u/tutantontut)\
**Post date:** [October 2, 2018, 6:26pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/3 "2018-10-02T18:26:26Z")

</div>

Yea your solution solves the relevant problem but creates others (in most cases) like you said.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [October 3, 2018, 6:46pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/4 "2018-10-03T18:46:11Z")

</div>

Nice solution.

For dealing with multiple keys you can generalize this solution to _every_ key using a HashMap with a boolean entry for any – keyPressed writes ‘true’, keyReleased writes ‘false’.

```
HashMap<Character,Boolean> keys;

```

Now you have a reliable previous state for any key on any keyboard, so you can make your counter solution more general-purpose:

```auto
void keyPressed(){
  if (keys.get(key)){ // is key already down?
    // do nothing
  } else {
    keys.put(key, Boolean.TRUE); // put key down
    switch(key){ // increment specific key counters or other actions
      case 'a':
        aPresses += 1;
        break;
      case 'b':
        bPresses += 1;
        break;
    }
  }
}

```

of course, you will also need to clear the flags in keyReleased():

```auto
void keyReleased(){
  keys.put(key, Boolean.FALSE);
}

```

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [August 22, 2019, 4:19am UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/5 "2019-08-22T04:19:43Z")

</div>

I get a NullPointerException on first key press.  
I got it working with code below:

```auto
import java.util.Map;

//HashMap<Character,Boolean> keys;
HashMap<Character, Boolean> keys = new HashMap<Character, Boolean>();

void setup()
  {
  println(keys.get(key)); //Checking state of key
  }
  
void draw()
  {
  }
  
void keyPressed(){
  
  if (keys.get(key) == null)
    {
  //do nothing
    }
  else if (keys.get(key)){ // is key already down?
    // do nothing
  } else {
    keys.put(key, Boolean.TRUE); // put key down
    switch(key){ // increment specific key counters or other actions
      case 'a':
        println(key);
        break;
      case 'b':
       println(key);
        break;
    }
  }
}

void keyReleased(){
  keys.put(key, Boolean.FALSE);
}

```

[https://processing.org/reference/HashMap.html](https://processing.org/reference/HashMap.html)

Also:  
I had to put key-value pairs in the HashMap otherwise it did not detect the first key press:

```auto
  keys.put('a', false);
  keys.put('b', false);

```

🙂

---

<div class="post-metadata">

**Author:** ![matheplica](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/matheplica/32/21035_2.png) [@matheplica](https://discourse.processing.org/u/matheplica)\
**Post date:** [August 22, 2019, 10:39am UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/6 "2019-08-22T10:39:05Z")

</div>

You can try only this in the setup : `hint(ENABLE_KEY_REPEAT);`

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 22, 2019, 5:25pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/7 "2019-08-22T17:25:53Z")

</div>

Thanks for sharing!

> [@glv](#):
>
> I get a NullPointerException on first key press. I got it working with code below:

Yes, you need to declare a new HashMap before you access it – this is true of an Object type that isn’t a primitive, like ArrayList, PImage, HashMap etc. You can do that in the header, although I generally do it in `setup()`.

> [@glv](#):
>
> I had to put key-value pairs in the HashMap otherwise it did not detect the first key press:

You have two options there.

1. prepopulate your map with the values that you will be manipulating – that is what you did for ‘a’ and ‘b’.

2. use [`getOrDefault()`](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#getOrDefault-java.lang.Object-V-) instead of `get()`. Then any keypress adds a key if it isn’t already there. You can skip prepopulating and also drop your code to ignore any key that isn’t already in the map:

> [@glv](#):
>
> if (keys.get(key) == null) { //do nothing }

One question: why are you checking an empty map for “key” in setup?

```auto
  println(keys.get(key)); //Checking state of key

```

The map is empty – and I _believe_ (?) that the Processing built-in “key” is also always empty until the first draw loop and event checks, so it won’t do anything in setup.

Here is a little self-adding HashMap along with a bit of console monitoring to show you how the map values change as you press and release keys.

```auto
import java.util.Map;
HashMap<Character, Boolean> keys;

void setup() {
  keys = new HashMap<Character, Boolean>();
}

void draw() {
}

void keyPressed() {
  if (keys.getOrDefault(key, Boolean.FALSE)) { // is key already down?
    // do nothing
  } else {
    keys.put(key, Boolean.TRUE); // put key down
    println("v", keys);
  }
}

void keyReleased() {
  keys.put(key, Boolean.FALSE);
  println("^", keys);
}

```

So if you type ‘a’, then hold-down “s-d-f” and release them, you get this:

> v {a=true}  
> ^ {a=false}  
> v {a=false, s=true}  
> v {a=false, s=true, d=true}  
> v {a=false, s=true, d=true, f=true}  
> ^ {a=false, s=true, d=true, f=false}  
> ^ {a=false, s=true, d=false, f=false}  
> ^ {a=false, s=false, d=false, f=false}

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [August 22, 2019, 8:53pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/8 "2019-08-22T20:53:41Z")

</div>

- [Studio.ProcessingTogether.com/sp/pad/export/ro.9cfU11egvzT6G](http://Studio.ProcessingTogether.com/sp/pad/export/ro.9cfU11egvzT6G)
- [Studio.ProcessingTogether.com/sp/pad/export/ro.91tcpPtI9LrXp](http://Studio.ProcessingTogether.com/sp/pad/export/ro.91tcpPtI9LrXp)
- [OpenProcessing.org/sketch/718355](http://OpenProcessing.org/sketch/718355)

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [August 25, 2019, 3:12pm UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/9 "2019-08-25T15:12:52Z")

</div>

Hello,

> [@jeremydouglass](#):
>
> One question: why are you checking an empty map for “key” in setup?
> 
> ```auto
> println(keys.get(key)); //Checking state of key
> 
> ```
> 
> The map is empty – and I _believe_ (?) that the Processing built-in “key” is also always empty until the first draw loop and event checks, so it won’t do anything in setup.

Your original code:

> [@jeremydouglass](#):
>
> if (keys.get(key)){ // is key already down? // do nothing }

resulted in a NullPointerException.

Some further exploration was needed…

```auto
  println(keys.get(key)); //Checking state of key

```

It indeed does something in setup()!  
I was able to see that the value keys.get(key) was “null”; this helped me as I was working through your posted code and go from there.

Processing documentation is sparse:

> **[HashMap / Reference](https://processing.org/reference/HashMap.html)**
>
> A HashMap stores a collection of objects, each referenced by a key. This is similar to an Array, only instead of accessing elements with a numeric index, a String is used. (If you…

and references this:

> **[JDK 21 Documentation - Home](https://docs.oracle.com/en/java/javase/21/)**
>
> The documentation for JDK 21 includes developer guides, API documentation, and release notes.

which does NOT reference **getOrDefault**!

This does reference **getOrDefault** :  
“[JDK 21 Documentation - Home](https://docs.oracle.com/javase/ **8** /docs/api/java/util/HashMap.html)”

I got this all sorted before you posted more on this and do not need to re **hash** those details.  
No pun intended! Thank you for elaborating on topic.

In the end, I better understand HashMaps.

I write a lot of code with multiple keys and have done similar to @GoToLoop with arrays in his examples and can now also use HashMaps.

I may post my code at a later time…

🙂

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [October 11, 2019, 12:23am UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/10 "2019-10-11T00:23:32Z")

</div>

This is my HashMap version for multiple key presses adapted from this topic:

```auto
// Description: Keyboard Control - HashMap version

HashMap<Character, Boolean> keys = new HashMap<Character, Boolean>();

boolean[] keysState = new boolean[512];

float s = 3;
float x, y, z;

float angle = TAU/200;

public void settings()
  {
  size(500, 500, P3D);
  }

public void setup()
  {
  hashMap();  
  }

public void draw()
  {  
  background(0);
  lights();
  translate(width/2, height/2, 0);
  rotateY(TAU/4);
  updateState();  
  rotateY(y); 
  rotateZ(z);
  rotateX(x);
  
 pushMatrix();
  noStroke();
  fill(128);
  box(s*90, s*10, s*40);
  noStroke();
 popMatrix();
  }
  

public void keyPressed()
  {
  if(keys.getOrDefault(key, Boolean.FALSE))
    {
    //Do nothing
    }
  else 
    {
    keys.put(key, Boolean.TRUE); // put key down
    println(key, keys.get(key));
    }
  }

public void keyReleased()
  {
  println("keyReleased");
  keys.put(key, Boolean.FALSE);
  println(key, keys.get(key));
  }
  
public void updateState() 
  {
  if(keys.get('7')) y += angle;
  if(keys.get('8')) y = 0;
  if(keys.get('9')) y -= angle;

  if(keys.get('4')) z += angle;
  if(keys.get('5')) z = 0;
  if(keys.get('6')) z -= angle;
  
  if(keys.get('1')) x += angle;
  if(keys.get('2')) x = 0;
  if(keys.get('3')) x -= angle;
  
  if(keys.get('0')) x = y = z = 0;
  }    
 
public void hashMap()
  {
  keys.put('1', false);
  keys.put('2', false);
  keys.put('3', false);
  keys.put('4', false);
  keys.put('5', false);
  keys.put('6', false);
  keys.put('7', false);
  keys.put('8', false);  
  keys.put('9', false); 
  keys.put('0', false);   
  }  

```

🙂

---

<div class="post-metadata">

**Author:** ![vincentstrebelle](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/vincentstrebelle/32/6963_2.png) [@vincentstrebelle](https://discourse.processing.org/u/vincentstrebelle)\
**Post date:** [November 1, 2019, 11:39am UTC](https://discourse.processing.org/t/solution-for-repeating-keypressed-while-holding-key/3989/11 "2019-11-01T11:39:00Z")

</div>

Hi, i wonder how can i use your method with a boolean, like this:

```auto
import processing.event.MouseEvent;

boolean[] mouses = new boolean[2];
boolean pressLeft = true;
boolean pressRight = true;
boolean actionLM = false;
boolean actionRM = false;

int leftClick;
int rightClick;

void setup(){
  size(200, 100);
  registerMethod("mouseEvent", this);
}

void draw(){
  background(255);
  
  mouseLeft();
  if(actionLM) leftClick+=1;
  fill(0);
  text("left " + leftClick, 10, 10);
  
  mouseRight();
  fill(0);
  text("right " + rightClick, 10, 25);
}

void mouseLeft(){
  if(pressLeft && mouses[0] == true){
    actionLM = true;
    pressLeft = false;
  }
  if(mouses[0] == false){
    actionLM = false;
    pressLeft = true;
  }
}

void mouseRight(){
  if(pressRight && mouses[1] == true){
    rightClick +=1;
    pressRight = false;
    actionRM = true;
  }
  if(mouses[1] == false){
    pressRight = true;
    actionRM = false;
  }
}
  
public void mouseEvent(MouseEvent e){
  int button = e.getButton();
  int buttonID = e.getAction();
  if(buttonID == MouseEvent.PRESS){
    mousePressedProcess(button);
  }
  if(buttonID == MouseEvent.RELEASE){
    mouseReleasedProcess(button);
  }
}
  
protected void mousePressedProcess(int button){
  if(button == PConstants.LEFT) mouses[0]=true;
  if(button == PConstants.RIGHT) mouses[1]=true;
}
  
protected void mouseReleasedProcess(int button){
  if(button == PConstants.LEFT) mouses[0]=false;
  if(button == PConstants.RIGHT) mouses[1]=false;
}

```

So, when i press the right button of the mouse, like in your example, its work.  
But i’m looking to use a boolean with my left button, and when i keep the left button pressed, the count don’t stop.

How can i make the left button like the right button but with a boolean ?  
So when i press the left button, the leftClick count increment by one and then i need to realese it and press it again to increment it again.

Thanks for your times guys
