# EventHandler Not Detecting KeyDown

I am trying to use EventHandler to detect KeyDown within a LocatorPane. Anytime I press a key inside the LocatorPane the proper action is not executed (doesn't matter which key I choose) but rather the the symbol of the key pressed appears in the next input line below the LocatorPane (i.e. it jumps out of the LocatorPane). I must be missing something simple because this works fine with {{"MouseClicked",2} :> (AppendTo[someList, 1]; Print[someList])} but not as shown below with {{"KeyDown", a} :> (AppendTo[someList, 1]; Print[someList])}. Btw, in case it's not obvious I am using the right mouse button for the click because the LocatorPane responds to the left button. Any suggestions on getting this to work properly with KeyDown? - GR

(* code below does not respond to "KeyDown" events but will respond properly to
"MouseClicked" *)

pts = {};

someList = {};

EventHandler[

LocatorPane[Dynamic[pts], Graphics[Circle[], ImageSize -> 500],
LocatorAutoCreate -> True,
Appearance -> {Graphics[{Red, Disk[]}, ImageSize -> 10],
Graphics[{Blue, Disk[]}, ImageSize -> 10]}],

{{"KeyDown", "a"} :> (AppendTo[someList, 1]; Print[someList])}

]

-
Do something like the following EventHandler[..,{"KeyDown":>CurrentValue["EventKey"]}] –  William Sep 21 '14 at 8:59

## 4 Answers

This is only a partial answer but may help.

See here for related case, it is probable that KeyDown "a" is reserved like "c".

This does not work:

DynamicModule[{someList = {}},
EventHandler[Graphics[{Blue, Disk[]}, ImageSize -> 100],
{{"KeyDown", "a"} :> (AppendTo[someList, 1]; Print[someList])}]]
(** doesn't work **)


But changing "a" to "x" does work"

DynamicModule[{someList = {}},
EventHandler[Graphics[{Blue, Disk[]}, ImageSize -> 100],
{{"KeyDown", "x"} :> (AppendTo[someList, 1]; Print[someList])}]]
(** does work **)

-
Hmm, your second example works once I select the yellow "frame" around the Graphics object but I don't know how to do this with a LocatorPane because the left mouse button moves the locators around the LocatorPane. Is there some way to select or bring up the yellow frame without using the left mouse button? Thanks.- GR –  user13999 Jul 24 '14 at 16:14
Don't know let me work on this. The target of the EventHandler will have to get the focus somehow, not sure how if it is not via the mouse. Perhaps the EventHandler does have to be attached to the cell and using SelectionMove as @hieron suggests. –  pjc42 Jul 25 '14 at 19:05

you can see that quite a few of the lowercase keys are used by DrawingTools which becomes active once the cursor focus is on the graphics. So, the easiest work-around is to use uppercase letters in your EventHandler as suggested by pjc42.

When the first argument of EventHandler does not contain a graphics object, this issue does not arise:

DynamicModule[{someList = {}},
EventHandler[Style["TEXT", 64,  Background -> Red],
{{"KeyDown", "a"} :> (AppendTo[someList, 1];  Print[someList])}]]


-
Thanks for the suggestion but I tried to change to {{"KeyDown","A"} instead of {{"KeyDown","a"} and it didn't work. Am I doing this incorrectly? Also, from trying out pjc42's suggestions above it seems that there is something about using LocatorPane that makes EventHandler with KeyDown not responsive. Any ideas why this might be so? Thanks. -GR –  user13999 Jul 24 '14 at 17:33
@user13999, this could be OS and/or version dependent; {"KeyDown","A"}  works as expected in Version 9.0.1.0 Windows 8 64bit. –  kguler Jul 24 '14 at 19:39

another idea but not an answer...

DynamicModule[{keyList = {}, pts = {}, input = Null},
EventHandler[
{LocatorPane[Dynamic[pts],
Graphics[Circle[], ImageSize -> 500],
LocatorAutoCreate -> True,
Appearance -> {Graphics[{Red, Disk[]}, ImageSize -> 10],
Graphics[{Blue, Disk[]}, ImageSize -> 10]}
(*LocatorPane**)],
Dynamic@keyList,
Dynamic@pts,
InputField@Dynamic@input (*
place cursor in input field after evaluation *)
} // Column,
{{"KeyDown", "a"} :> (AppendTo[keyList, "a"]; Speak["a"]),
{"KeyDown", "b"} :> (AppendTo[keyList, "b"]; Speak["b"]),
{"KeyDown", "c"} :> (AppendTo[keyList, "c"]; Speak["c"])
} , PassEventsDown -> True (*EventHandler**)]
(*DynamicModule**)]


## Edit1:

Probably this is a solution for your problem. Instead of EventHandler I tried CellEventActions with SelectionMove

DynamicModule[{pts = {}, keyAction},

keyAction = CellPrint@ExpressionCell[#,

Deployed -> True,
(* especially no text cursor *)

CellEventActions -> {
{"KeyDown", "a"} :> Speak@"a",
{"KeyDown", "b"} :> Speak@"b",
"KeyDown" :> Null
}(*ExpressionCell**)] &;

LocatorPane[Dynamic[pts],
Graphics[Circle[], ImageSize -> 500],
LocatorAutoCreate -> True,
Appearance -> {Graphics[{Red, Disk[]}, ImageSize -> 10],
Graphics[{Blue, Disk[]}, ImageSize -> 10]}
(*LocatorPane*)] // keyAction

(*DynamicModule**)]; SelectionMove[
InputNotebook[], Before, CellContents];


I hope, it meets your needs. I'm not quite sure, but this new version should work in: M7,M8,M9,M10

-
Thanks for the suggestion. I tried this out and it works but only once I've clicked in the input field after the initial evaluation. Until then any of the KeyDown specified keys jump out of the LocatorPane. Any idea why it behaves this way rather than allowing me to immediately use the KeyDown keys after evaluation? –  user13999 Jul 24 '14 at 16:09
Using InputField is not necessary, but it demonstrates the problem obviously. I tried to place and to keep the text cursor focus inside cell context using the SelectionMove function. There must be a simple way ..., still looking for. –  hieron Jul 24 '14 at 19:59
Thanks a lot, using CellEventActions seems to be getting the job done. –  user13999 Jul 29 '14 at 23:03

You can do the following as a workaround in M9.

 EventHandler["t",{"KeyDown":>
If[CurrentValue["EventKey"]=="a",
Print["a"]
]
}
]

-