9
$\begingroup$

What might be the most elegant way to throttle the a,s functions triggered by an EventHandler such that the InputField doesn't get to far behind in the following example? Just to clarify. I am looking to have the queued functions stop executing after either the a or s keys are released.

Here is an illustration of a similar issue to the one I am experiencing while in the Graphics3D element.

i = 0;
a[] := (Pause[RandomInteger[{1, 9}]*.1]; i++;);
s[] := (Pause[RandomInteger[{1, 9}]*.1]; i--;);
EventHandler[InputField[Dynamic@i, Number], {"KeyDown" :> (
    If[CurrentValue["EventKey"] == "a",
     a[], s[]
     ]
    )}
 ]

EDIT: If you hold down the a key I would like the unrun functions to either not run or somehow throttle the number of times the function is executed such that you can successfully hold down the a key for 2 seconds and then immediately(or as quickly as possible) hold down s key to subtract without a delay in the response. Ideally I would like to use the EventHandler KeyReleased option but I am currently unable to get such key to work.

$\endgroup$
4
  • $\begingroup$ Just to clarify, does "too far behind" mean your example should not increment/decrement when I press a key multiple times during the pause or are you hoping for some type of buffered response? $\endgroup$ Sep 21, 2014 at 14:46
  • $\begingroup$ @bobthechemist If you hold down the a key I would like the unrun functions to either not run or somehow throttle the number of times the function is executed such that you can successfully hold down the a key for 2 seconds and then immediately(or as quickly as possible) hold down s key to subtract without a delay in the response. $\endgroup$
    – William
    Sep 21, 2014 at 16:58
  • $\begingroup$ @bobthechemist I believe KeyReleased would make this process a lot easier although I have been unable to get such EventHandler to work currently $\endgroup$
    – William
    Sep 21, 2014 at 17:08
  • $\begingroup$ This I believe is a duplicate of this if not similar mathematica.stackexchange.com/questions/5246/… $\endgroup$
    – William
    Apr 14, 2016 at 20:41

2 Answers 2

1
$\begingroup$

You can always make a back-end for it and check the response time on that. Here's a little example of a back-end I've been working with:

$eventHandlerData =
  <|
   "ResponseDelay" -> Quantity[1, "Seconds"],
   "_ResponseDelay" :>
    With[{n = Now},
     AbsoluteTime[n + $eventHandlerData["ResponseDelay"]] -
      AbsoluteTime[n]
     ],
   "CallDelay" :>
    ($eventHandlerData[
       "_EventAbsoluteTime"] - $eventHandlerData[
       "LastCallAbsoluteTime"]),
   "LastCallEventTime" -> 0,
   "LastCallAbsoluteTime" -> 0,
   "x" -> Function[Print["!"]],
   "DefaultEvent" -> (Print[$eventHandlerData["EventKey"]] &)
   |>;
callEventHandler[] :=
  Catch[
   $eventHandlerData =
    Join[
     $eventHandlerData,
     Association@CurrentValue["EventData"],
     <|
      "EventKey" -> CurrentValue["EventKey"],
      "EventAbsoluteTime" -> CurrentValue["EventAbsoluteTime"],
      "_EventAbsoluteTime" -> AbsoluteTime[]
      |>];
   If[$eventHandlerData["_ResponseDelay"] > $eventHandlerData[
      "CallDelay"],
    Throw[$Failed]
    ];
   $eventHandlerData["LastCallAbsoluteTime"] =
    $eventHandlerData["_EventAbsoluteTime"];
   $eventHandlerData["LastCallTime"] =
    $eventHandlerData["EventAbsoluteTime"];
   Lookup[$eventHandlerData,
     $eventHandlerData@"EventKey",
     $eventHandlerData@"DefaultEvent"
     ][]
   ];
EventHandler[expr,
 {
  "KeyDown" :> callEventHandler[],
  {"MenuCommand", "HandleShiftReturn"} :> callEventHandler[],
  PassEventsDown -> False
  }
 ]

Note that I had to fall back to AbsoluteTime as I'm not entirely sure what the timings in CurrentValue["EventAbsoluteTime"] are.

You can then extend it to work in an indexable manner with DynamicModule that way you don't have to worry about cleaning up the backend when you're done with it.

$\endgroup$
0
$\begingroup$

This doesn't work completely for reasons I don't know why, but the following seems to help some by using an InputField to monitor the keyboard input.

str = "";
i = 0;
a[] := (Pause[RandomInteger[{1, 9}]*.1]; i++;);
s[] := (Pause[RandomInteger[{1, 9}]*.1]; i--;);
Dynamic[Refresh[
  t = 0;
  Map[
   (If[# == "a", a[], s[]]) &,
   Select[StringSplit[str, ""], t++ < 3 &]
   ];
  str = "";
  , UpdateInterval -> 1], TrackedSymbols -> {}]
InputField[Dynamic@str, String, ContinuousAction -> True]
InputField[Dynamic@i, Number]
$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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