11 Replies Latest reply: Mar 19, 2013 4:48 AM by 963802 RSS

    KEY_TYPED event - find key with CTRL modifier?

    963802
      Greetings,
      I am trying to get the key associated with the CTRL modifier with a KEY_TYPED event. This works for all modifiers except CTRL. The difference from the output below is the "isShortcutDown" is true for CTRL and false for all the other modifiers. How do I disable the shortcut for CTRL?


      [CTRL +key Output]
      Handle - KeyEvent [source = javafx.stage.Stage@127c376a, target = ComboBox[id=mappingCB, styleClass=combo-box-base combo-box], eventType = KEY_TYPED, consumed = false, character = , text = , code = UNDEFINED, controlDown, shortcutDown]
      KEY TYPED
      key:
      is shift down: false
      is ctrl down: true
      is alt down: false
      is meta down: false
      is shortcut down:: true

      [ALT +key Output]
      Handle - KeyEvent [source = javafx.stage.Stage@127c376a, target = ComboBox[id=mappingCB, styleClass=combo-box-base combo-box], eventType = KEY_TYPED, consumed = false, character = d, text = , code = UNDEFINED, altDown]
      KEY TYPED
      key: d
      is shift down: false
      is ctrl down: false
      is alt down: true
      is meta down: false
      is shortcut down:: false

      Thanks
        • 1. Re: KEY_TYPED event - find key with CTRL modifier?
          James_D
          As I understand it, a KeyTyped event will give you the unicode character represented by the key combination in the getCharacter() method. For ctrl-D this is the unicode character with value 4 (end-of-transmission character). Since this is not a printable character, it's not displaying in your output. You could do something like
          String eventChar = event.getCharacter();
          if (eventChar.length()==1 && eventChar.charAt(0)=='\u0004') {
            // ctrl-D was pressed
          }
          but this probably isn't the best way. The getCode() method, in general, gives you information about the physical key used to generate the event, but getCode() always returns KeyCode.UNDEFINED for KeyTyped events. The reason is that KeyTyped events encapsulate the entire combination of keys. (So the getCharacter() method will give "d" for just the D key, without shift or caps lock, but "D" for the D key with Shift or Caps Lock.)

          For lower-level events, such as KeyReleased events, the getCode() method will return the code for the physical key that generated the event. So in your example, if you register your handler with a setOnKeyReleased(...) method, you should be able to do something like
          public void handle(KeyEvent event) {
            if (event.getCode()==KeyCode.D && event.isCtrlDown()) {
              // ctrl-D was pressed...
            }
          }
          The isShortcutDown() method tells you if the appropriate meta-key for a keyboard shortcut was pressed when the event occurred. On Windows this is the ctrl key; on Mac it's the Command key. This isn't preventing you from detecting the key that was pressed.
          • 2. Re: KEY_TYPED event - find key with CTRL modifier?
            shakir.gusaroff
            You can also use a keycombination:
                    final KeyCombination keyComb = new KeyCodeCombination(KeyCode.D,
                            KeyCombination.CONTROL_DOWN);
                    scene.addEventHandler(KeyEvent.KEY_RELEASED, new EventHandler<KeyEvent>() {
                        @Override
                        public void handle(KeyEvent event) {
            
                            if (keyComb.match(event)) {
                                System.out.println("Ctrl+D was pressed");
                            }
                        }
                    });
            • 3. Re: KEY_TYPED event - find key with CTRL modifier?
              963802
              On KEY_RELEASED events, there are 2 events fired (one for "D" and one for "CTRL"). This is a problem for my application because I am trying to assign key presses based on user input. Does this mean I have to write some threaded timing code to figure out if the user is holding down CTRL and another key (wait 20ms or something)?

              Here is the output generated from a CTRL+D.
              Handle - KeyEvent [source = javafx.stage.Stage@195fba5, target = ComboBox[id=mappingCB, styleClass=combo-box-base combo-box], eventType = KEY_RELEASED, consumed = false, character = ^@, text = ^D, code = D, controlDown, shortcutDown]
              KEY Released
              code: D
              is shift down: false
              is ctrl down: true
              is alt down: false
              is meta down: false
              Handle - KeyEvent [source = javafx.stage.Stage@195fba5, target = ComboBox[id=mappingCB, styleClass=combo-box-base combo-box], eventType = KEY_RELEASED, consumed = false, character = ^@, text = , code = CONTROL]
              KEY Released
              code: CONTROL
              is shift down: false
              is ctrl down: false
              is alt down: false
              is meta down: false
              • 4. Re: KEY_TYPED event - find key with CTRL modifier?
                963802
                The KeyCombination method would require me to generate a KeyCombination for each 104+ keys on the keyboard since I want the user to be able to arbitrarily assign keys. Is there an easy way of doing this?
                • 5. Re: KEY_TYPED event - find key with CTRL modifier?
                  James_D
                  The KeyCode enum has various useful methods:
                  isLetterKey()
                  isDigitKey()
                  isModifierKey()
                  etc etc

                  So you could, for example, ignore key released events from modifier keys.
                  • 6. Re: KEY_TYPED event - find key with CTRL modifier?
                    James_D
                    Something like:
                    scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
                      @Override
                      public void handle(KeyEvent event) {
                        KeyCode keyCode = event.getCode();
                        if (keyCode != KeyCode.UNDEFINED && ! keyCode.isModifierKey() && event.isCtrlDown()) {
                          KeyCombination keyComb = new KeyCodeCombination(keyCode, KeyCombination.CONTROL_DOWN);
                          // register keyComb as required...
                        }
                      }
                    });
                    It's probably better to use event.isShortcutDown() (and KeyCombination.SHORTCUT_DOWN) instead of event.isCtrlDown(); it will make your application portable (but will work exactly the same on a windows system if that's not something you care about). You obviously need a bit more logic if you want the user to be able to choose to register different modifier keys.
                    • 7. Re: KEY_TYPED event - find key with CTRL modifier?
                      963802
                      The problem with this is that the user should be able to assign CTRL, ALT, and any modifier key. So CTRL can't be ignored.
                      • 8. Re: KEY_TYPED event - find key with CTRL modifier?
                        James_D
                        I don't think this is a problem. You want to ignore key-released on any modifier key; you just want to know what modifier keys are pressed when any other key is released, no?

                        Unless you are proposing to allow the user to press a modifier key with no other key pressed, and have that invoke some action. I'm not sure there's an easy way to do that, but it would be a pretty non-standard UI anyway.
                        • 9. Re: KEY_TYPED event - find key with CTRL modifier?
                          963802
                          I want to be able for the user to assign CTRL to an action. I also want the user to be able to assign CTRL+D or ALT+D for instance.

                          As for assigning CTRL to an action, its very standard for gaming. CTRL is often used in FPS's for the crouch action.
                          • 10. Re: KEY_TYPED event - find key with CTRL modifier?
                            James_D
                            So in that case you will need to implement some more complex logic. I don't think it needs to be as complex as implementing timers, etc, though.

                            For example:
                            private boolean ignoreControlRelease = false ;
                            
                            ...
                            
                            scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
                              @Override
                              public void handle(KeyEvent event) {
                                 KeyCode code = event.getCode();
                                 if (code==KeyCode.CONTROL && ! ignoreControlRelease) {
                                   // process control key (on its own)
                                 } else if (event.isControlDown()) {
                                   ignoreControlRelease = true ;
                                   // process control + code ...
                                 } else {
                                   ignoreControlRelease = false ;
                                 }
                              }
                            });
                            and similarly for other modifier keys.
                            • 11. Re: KEY_TYPED event - find key with CTRL modifier?
                              963802
                              Thank you for your help! Your suggestion works!

                              Here is the complete code.
                              private boolean ignoreModifierRelease = false;
                              ...
                                       KeyEvent keyEvent = (KeyEvent)event;
                              
                                       if (keyEvent.getCode() == KeyCode.CONTROL && !ignoreModifierRelease) {
                                        setKeyPressed(keyEvent, "KEY");
                                       } else if (keyEvent.isControlDown()) {
                                        ignoreModifierRelease = true;
                                        setKeyPressed(keyEvent, "CTRL");
                                       }else if (keyEvent.getCode() == KeyCode.ALT && !ignoreModifierRelease) {
                                        setKeyPressed(keyEvent, "KEY");
                                       } else if (keyEvent.isAltDown()) {
                                        ignoreModifierRelease = true;
                                        setKeyPressed(keyEvent, "ALT");
                                       }else if (keyEvent.getCode() == KeyCode.SHIFT && !ignoreModifierRelease) {
                                        setKeyPressed(keyEvent, "KEY");
                                       } else if (keyEvent.isShiftDown()) {
                                        ignoreModifierRelease = true;
                                        setKeyPressed(keyEvent, "SHIFT");
                                       }else if (keyEvent.getCode() == KeyCode.META && !ignoreModifierRelease) {
                                        setKeyPressed(keyEvent, "KEY");
                                       } else if (keyEvent.isMetaDown()) {
                                        ignoreModifierRelease = true;
                                        setKeyPressed(keyEvent, "META");
                                       } else if(!ignoreModifierRelease){
                                        setKeyPressed(keyEvent, "KEY");
                                       } else {
                                        ignoreModifierRelease = false;
                                       }