Multi-Button KeyPress

What is the JUCE way I should go about to trigger something in my application if two different keys are pressed at the same time?

For example, let’s say I map the ‘1’ key on my keyboard to do something in my application. I also map the ‘2’ key to do something else. But I also want to have another separate trigger if the keys ‘1’ & ‘2’ are held down simultaneously.

I’m basically trying to setup a kind of toggle chain of three buttons to activate a specific button for each of these three key combinations: ‘1’ pressed independently, ‘2’ pressed independently, and ‘1’ & ‘2’ pressed/held simultaneously.

It’s actually a simple Logic problem, there’s no specific Juce way of doing it:

if(isPressed(KeyA) && !isPressed(KeyB)) { }
else if(!isPressed(KeyA) && isPressed(KeyB)) { }
else if(isPressed(KeyA) && isPressed(KeyB)) { }

Write an “isPressed(key)” function that returns true/false

I’m still confused on how to actually implement this.

I’ve created two KeyPress objects in a component and mapped them to keys.
I’ve also made that component a KeyListener so that it can receive a callback when keys are pressed.
I have to implement this callback in my component via the pure virtual function: bool keyPressed (const KeyPress &key, Component *originatingComponent).

But now I’m confused because within this callback, I only have reference to the one KeyPress the function gives me called key. So within this callback I can’t actually check if multiple keys are pressed. I only have access to this one key that initiated the callback.

you have two approaches:

1). build something that will store currently pressed keys. whenever you get a keyPressed() event happening, you can check your keysThatHaveBeenPressed for the key in question. Building it similar to how the MidiKeyboardState class handles storing NoteOn’s and NoteOff would work really well.

  1. use static bool KeyPress::isKeyCurrentlyDown() and check for the key that you are looking for:
if( key == aKey ) {
  if(KeyPress::isKeyCurrentlyDown(bKey) ) { aKey and bKey are pressed }
  else if( !KeyPress::isKeyCurrentlyDown(bKey) { only aKey is pressed }
} else if( key == bKey ) { 
  if( KeyPress::isKeyCurrentlyDown(aKey)) { bKey and aKey are pressed }
  else if( !KeyPress::isKeyCurrentlyDown(aKey) { only bKey is pressed }
} etc
1 Like

Oh okay, this makes sense! Thank you!
The only problem I seem to be having is that the KeyListener portion of my Component is not registering any KeyPresses. I’m running a test to try and output the keypress code to the console, but it will not output anything.

class MyComponent : public Component, private KeyListener
{
    public:
        MyComponent()
        : aKey('A'),
          bKey('B')
        {
        }

        // . . .

    private:
        KeyPress aKey, bKey;


        bool keyPressed (const KeyPress &key, Component *originatingComponent) override
        {
            // This is where I'm going to put my if statements to check for buttons down
            // . . .
            // But here is my console test to make sure this function gets called:
            std::cout << key.getKeyCode();
        }
}

Am I setting up my KeyListener incorrectly?

you didn’t add your class as a listener in the constructor:

void Component::addKeyListener ( KeyListener * newListener )

you gotta addKeyListener(this); in your constructor and removeKeyListener(this); in your destructor.

If it’s a component you do not need a key listener. Just override bool Component::keyPressed (const KeyPress &key). Be sure to indicate that you want keyboard focus with setWantsKeyboardFocus (true); and call grabKeyboardFocus sometime later. You may need to call grabKeyboardFocus outside of your constructor as the parent component may override this again.

1 Like

@fabian 's solution worked! Thanks!

If anyone else comes along this topic, my final working code was put together in this structure:

class MyComponent : public Component
{
    public:
        MyComponent()
        : aKey('A'),     // Assigns keyboard key 'A' to this KeyPress
          bKey('B')     // Assigns keyboard key 'B' to this KeyPress
          {
          }

        // . . .

          bool keyPressed (const KeyPress &key) override
          {
              if (key = aKey)
              {
                  if (!bKey.isCurrentlyDown())
                      // Stuff to do only when 'A' is pressed . . .
                  else
                     // Stuff to do when 'A' was pressed while 'B'
                     // was being held down . . .
              }
              else if (key == bKey)
              {
                  if (!aKey.isCurrentlyDown())
                      // Stuff to do only when 'B' is pressed . . .
                  else
                     // Stuff to do when 'B' was pressed while 'A'
                     // was being held down . . .
              }
              else { }
          }

    private:
        KeyPress aKey, bKey;
        // . . .
1 Like