Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is there a way to detect when a key is released, similar to

EventHandler[InputField[], {"KeyDown", "k"} :> Print["k pressed"]]

It seems such detection isn't available at first glance, perhaps it can be achieved some other way?

Alternatively is there a way to detect which keys are currently pressed? I know that;

CurrentValue["ModifierKeys"] 

Works for shift, ctrl and such, but I can't seem to figure out how to get a list of regular keys being pressed.

Edit: CurrentValue["EventKey"] does not seem to work for this purpose as it only detects keydown events, thus you cannot do something like the following which detects shift-up

shiftDown = False;
Dynamic[
If[MemberQ[CurrentValue["ModifierKeys"], "Shift"], (shiftDown = True;), 
      If[shiftDown, (shiftDown = False; Print["Shift up code"])]
    ]
]

link to MathGroup post

share|improve this question
2  
paging Yu-Sung Chang... –  rm -rf May 6 '12 at 19:12
4  
The fact that the KeyDown event fires continuously while the key is pressed seems coherent with a timed scan of the keyboard, and not a real (interrupt driven) event handler. If that is the case, you'll never get a KeyUp event. –  belisarius May 6 '12 at 19:21
    
If anyone knows for sure if this is the case, it would be nice with confirmation of this. –  jVincent May 6 '12 at 20:01
    
Thanks for the edit. The reason is to keep things together for readers of both threads. –  Szabolcs May 7 '12 at 21:20
add comment

3 Answers

To answer the second part of your question, you can use CurrentValue["EventKey"] to get the current key that is being pressed. Modifying your example above:

EventHandler[InputField[], "KeyDown" :> Print[CurrentValue["EventKey"]]]
share|improve this answer
    
Thank you for your answer. I realize that you can detect which key triggered the event inside an event handler, however for the second part of my question I was looking for a way to cercumvent the lack of a keyup event, by having something similar to Dynamic[CurrentValue["ModifierKeys"]] which can be used to along with tricks to for example detect when shift is lifted. –  jVincent May 6 '12 at 19:25
    
CurrentValue["EventKey"] however does not detect all keys, only alphanumeric and punctuation keys, but no Control, Shift, Enter, etc. –  István Zachar Aug 31 '13 at 8:04
add comment

Edit: Updated to register any key presses

Whenever an EventHandler does not handle something continuously, one can set up a listener manually using scheduled tasks. Here, the task task is initiated when the InputField is displayed, that scans the state of the Shift key. You can put whatever code you want to be evaluated on keypress in the update function.

DynamicModule[{task, pressed = {}, on = False, last, time, modNew, modOld, event = {}, 
  mods = {"AltKey", "CommandKey", "ControlKey", "OptionKey", "ShiftKey"}},
 Column@{
   Dynamic@pressed,
   EventHandler[
    InputField[], {"KeyDown" :> (If[! on, on = True]; last = SessionTime[];
                                 event = CurrentValue@"EventKey")}, 
    PassEventsDown -> True]
   },
 Initialization :> (
   modOld = False /@ mods;
   If[FreeQ[ScheduledTasks[], task], task = RunScheduledTask[
      time = SessionTime[];
      modNew = CurrentValue /@ mods;
      If[modNew =!= modOld, pressed = Pick[mods, modOld]];
      If[on && time - last > .55, on = False; pressed = {event}];
      modOld = modNew,
      .05]];
   ),
 Deinitialization :> If[MemberQ[ScheduledTasks[], task], RemoveScheduledTask@task]
 ]

Image shows the update due to successive key presses of any key (that can be registered):

enter image description here

For control keys, the method is simply checking CurrentValue-s while the task is running. The hard part is to get the letter/digit/punctuation keys to be registered. For those, the code measures the time between successive updates (time and last) which are calculated while the (non-control-)key is held pressed. Since Windows uses a 0.5 sec time delay before starting to flood-type when a key is pressed, one has to wait at least the same amount of time before being able to tell whether the key was released or it is still pressed and continuous typing is about to start. Thus registering the release of letter-keys can only happen when enough time (.55 sec) has been spent since the last update.

Since the scheduled task should run in the background as long as the InputField is on screen, there should be a method to destroy it only when the InputField is destroyed, hence the Deinitialization code.

share|improve this answer
    
@Mr.Wizard I've experimented with this kind of update, with no avail. If you could make it update i in "discrete steps" it would be a useful approach, but this still does not work: old = False; i = 0; Dynamic[If[old =!= shift && shift, i++]; {shift, i}, old = shift; shift := CurrentValue@"ShiftKey"]. –  István Zachar Aug 31 '13 at 10:49
    
@IstvánZachar Try old = False; i = 0; Dynamic[If[old =!= shift && shift, i++]; old = shift; shift := CurrentValue@"ShiftKey"; {shift, i}] –  Hector Aug 31 '13 at 11:11
    
@Hector Well that's certainly a lot cleaner! –  Mr.Wizard Aug 31 '13 at 11:14
    
@Hector I just realized similar function is already in the question, and this is about other keys, not modifiers. Oh well, it was fun playing with it. –  Mr.Wizard Aug 31 '13 at 11:23
    
I'm afraid without extension to letters etc., not just modifiers, this answer brings nothing new. Do you think that's possible? –  Mr.Wizard Aug 31 '13 at 11:26
show 4 more comments

You can try using NotebookEventActions see the given example in an other subject.

displaying = True;

SetOptions[EvaluationNotebook[], 
 NotebookEventActions :> {{"KeyDown", "k"} :> (If[! displaying, 
      Print["k press"]]), 
   "DownArrowKeyDown" :> (If[! displaying, Print["down press"]]), 
   "MouseClicked" :> (If[displaying, displaying = False])}]

the related thread Make EventHandler work for clicks and keys in a Dynamic display

share|improve this answer
2  
I fear this has the exact same problem, you cannot detect keyUp, since events only trigger on keyDown. –  jVincent May 6 '12 at 19:50
3  
If it is really so crucial you may use JLink to call java API in mathematica. There defined key up events. –  s.s.o May 6 '12 at 20:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.