TransWikia.com

How to solve the problem of EventHandler losing focus?

Mathematica Asked by xingzheshengcun on July 29, 2021

Manipulate[EventHandler[
  Row[{TableForm[Map[NumberForm[#, {6, 2}] &, {{x, y}, dir}, {2}], 
     TableHeadings -> {{"{x,y}", "dir"}, {"X", "Y"}}]
    , Graphics[{Thick, Green, PointSize[.02], Point[{x, y}], 
      Line[{{x, y}, {x, y} + dir}]}
     , ImageSize -> {200, 200}, PlotRange -> {{0, 10}, {0, 10}}, 
     Background -> Gray]}]
  , {"LeftArrowKeyDown" :> (dir = RotationTransform[.1][dir])
   , "RightArrowKeyDown" :> (dir = RotationTransform[-.1][dir])
   , "UpArrowKeyDown" :> (If[0 < x + dir[[1]] < 10, x += dir[[1]]]; 
     If[0 < y + dir[[2]] < 10, y += dir[[2]]])
   , "DownArrowKeyDown" :> (If[0 < x - dir[[1]] < 10, x -= dir[[1]]]; 
     If[0 < y - dir[[2]] < 10, y -= dir[[2]]])}]
 , {{x, 3.2}, ControlType -> None}, {{y, 4.8}, 
  ControlType -> None}, {{dir, {0, 1}}, ControlType -> None}
 ]

When I hit the direction key in the right graphic area a few times, sometimes the right graphic area will lose focus and the focus will run to the left table area. As a result, if you want the right graphic area to continue to respond to the direction key, you have to click the right graphic area with the mouse. The action is very discontinuous! How can we make the right graphic area not lose focus? Looking forward to the answer, thank you.

2 Answers

Please send a bug report to Wolfram Research ([email protected]). Until you get a patch for your Mathematica version you could the following code ( I only tested it on Windows, but it should work on Mac and Linux, too, I think ):

    Manipulate[
      EventHandler[
        Grid[{{Pane[#, Alignment -> Center, ImageSize -> 222]& @ 
               TableForm[Map[NumberForm[#, {6, 2}]&, {{x, y}, dir}, {2}], 
               TableHeadings -> {{"{x,y}", "dir"}, {"X", "Y"}}, TableAlignments -> Right], 
               (*Deploy @ *)Graphics[{Thick, Green, PointSize[.02], Point[{x, y}], Line[{{x, y}, {x, y} + dir}]}, 
               ImageSize -> {200, 200}, PlotRange -> {{0, 10}, {0, 10}}, Background -> Gray]
               }}, Spacings -> 1, Alignment -> {Left, Right}, Dividers -> None
        ], {"LeftArrowKeyDown" :> (dir = RotationTransform[.1][dir];
        
        click[])
        , 
        "RightArrowKeyDown" :> (dir = RotationTransform[-.1][dir];
        
        click[])
        , "UpArrowKeyDown" :> (If[0 < x + dir[[1]] < 10,
            x += dir[[1]]
          ];      
          If[0 < y + dir[[2]] < 10,
            y += dir[[2]]
          ];     
          click[]
        ), "DownArrowKeyDown" :> (If[0 < x - dir[[1]] < 10,
            x -= dir[[1]]
          ];
          
          If[0 < y - dir[[2]] < 10,
            y -= dir[[2]]
          ];     
          click[]
        )
      }
    ], {{x, 3.2}, ControlType -> None}, 
       {{y, 4.8}, ControlType -> None}, 
       {{dir, {0, 1}}, ControlType -> None}, 
       Initialization :> (click[] := (
        Needs["JLink`"];   
        JLink`InstallJava[];
        JLink`LoadJavaClass["java.awt.event.InputEvent"];
        robot = JLink`JavaNew["java.awt.Robot"];
        robot @ mousePress[InputEvent`BUTTON1UMASK];
        robot @ mouseRelease[InputEvent`BUTTON1UMASK];
        Pause[.01]
      );
    )
]

Answered by Rolf Mertig on July 29, 2021

Your Manipulate's body (first argument) depends on x, y and dir. If any of them changes the whole body is reevaluated and rendered which means the EventHandler after the arrow key press is a new EventHandler, Graphics is also new so it is not surprising that the selection is lost and not restored sometimes.

You can avoid this by making sure that only the essential part is refreshed. Just put Dynamics here and there. It is called 'nesting Dynamics' and explained in tutorial/AdvancedDynamicFunctionality and various threads here:

   EventHandler[
 Row[{Dynamic@
    TableForm[Map[NumberForm[#, {6, 2}] &, {{x, y}, dir}, {2}], 
     TableHeadings -> {{"{x,y}", "dir"}, {"X", "Y"}}], 
   Graphics[{Thick, Green, PointSize[.02], Point[Dynamic@{x, y}], 
     Line[Dynamic@{{x, y}, {x, y} + dir}]}, ImageSize -> {200, 200}, 
    PlotRange -> {{0, 10}, {0, 10}}, 
    Background -> Gray]}], {"LeftArrowKeyDown" :> (dir = 
     RotationTransform[.1][dir]), 
  "RightArrowKeyDown" :> (dir = RotationTransform[-.1][dir]), 
  "UpArrowKeyDown" :> (If[0 < x + dir[[1]] < 10, x += dir[[1]]];
    If[0 < y + dir[[2]] < 10, y += dir[[2]]]), 
  "DownArrowKeyDown" :> (If[0 < x - dir[[1]] < 10, x -= dir[[1]]];
    If[0 < y - dir[[2]] < 10, y -= dir[[2]]])}]

Answered by Kuba on July 29, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP