3
$\begingroup$

I seem to be able to use EventHandler to handle mouse events, but not keyboard events. Here is a working example with MouseClicked -- it makes the picture smaller every time the right mouse button is clicked. For the example, the t variable is a dummy and doesn't do anything.

s = 1; Manipulate[EventHandler[{s, ImageResize[img, Scaled[s]]}, 
                  {{"MouseClicked", 2} :> (s = 0.9 s)}], {t, 1/2, 2}]

But if I replace the MouseClicked with a

s = 1; Manipulate[EventHandler[{s, ImageResize[img, Scaled[s]]}, 
                 {{"KeyDown", "."} :> (s = 0.9 s)}], {t, 1/2, 2}]

Then it doesn't change the size. It appears that the focus of the keyboard/typing is not passed to the correct level. This is basically the same as this question which was asked several years ago and doesn't appear to have been successfully answered (at least none of the proposed answers works in my case).

$\endgroup$
2
  • $\begingroup$ This work for "x", not ".", if you click the image before pressing the key (hardly a sarisfactory solution): CellPrint[ ExpressionCell[ Manipulate[ EventHandler[{s, ImageResize[img, Scaled[s]]}, {{"KeyDown", "x"} :> (s = 0.9 s)}], {t, 1/2, 2}], "Output", CellEventActions -> {PassEventsDown -> True}]]. Maybe it will help.... $\endgroup$ – Michael E2 May 2 '20 at 21:28
  • $\begingroup$ Your image double click example doesn't work with my mac trackpad... $\endgroup$ – M.R. May 4 '20 at 20:40
3
$\begingroup$

It is a mater of keyboard focus.

You have to use Dynamic wrappers within your event handler and you must have the visible value of s selected so it has the keyboard focus when you press . .

This works:

s = 1;
img = ExampleData[{"TestImage", "House"}];
Manipulate[
  EventHandler[
    Dynamic @ {s, ImageResize[img, Scaled[s]]},
    {{"KeyDown", "."} :> (s = 0.9 s)}],
 {t, 1/2, 2}]

but you have to reselect the value of s each time after pressing . because the focus is lost. This works better because the value of s keeps the focus.

s = 1; 
img = ExampleData[{"TestImage", "House"}];
Manipulate[
  EventHandler[
    {Dynamic @ s, Dynamic @ ImageResize[img, Scaled[s]]},
    {{"KeyDown", "."} :> (s = 0.9 s)}],
 {t, 1/2, 2}]

demo

$\endgroup$
3
  • $\begingroup$ Thanks -- this is a great improvement, though still not perfect. The reason I wish to use the keyboard commands is because I have already overloaded the mouse with things it needs to click and right-click on... so it's not practical to have to click somewhere to keep the focus in the right place. But thanks for trying! $\endgroup$ – bill s May 3 '20 at 3:02
  • $\begingroup$ @bills. I think in your place I would consider implementing the additional actions with buttons rather than keystrokes. $\endgroup$ – m_goldberg May 3 '20 at 12:52
  • $\begingroup$ Yes, I think that's a good idea... I may try a palette (CreatePalette) with some buttons or checkboxes. $\endgroup$ – bill s May 3 '20 at 12:57
1
$\begingroup$

Thanks to m_goldberg and Michael E2 for their insights. Unfortunately, the use of keyboard shortcuts seems finicky. What I ended up doing was to use the Mouse click along with control/option/shift keys (using the CurrentValue hint from Michael E2's post).

What this (toy version) does is to use the mouse and to grow the picture for control-click and to shrink the picture for shift-control-click. The advantage is that there is no need to worry about the focus: as long as the mouse is inside the Manipulate, it functions as desired.

s = 1; img = ExampleData[{"TestImage", "Aerial"}];
Manipulate[EventHandler[{s, ImageResize[img, Scaled[s]]}, 
 "MouseClicked" :> 
    Which[CurrentValue["ControlKey"] && CurrentValue["ShiftKey"], (s = 0.9 s), 
    CurrentValue["ControlKey"] && Not[CurrentValue["ShiftKey"]], (s = 1.1 s)]], 
{t, 1/2, 2}]
$\endgroup$
1
$\begingroup$

If you put the output in its own notebook, you could use NotebookEventActions:

SetOptions[EvaluationNotebook[], 
  NotebookEventActions -> {{"KeyDown", "."} :> (s = 0.9 s)}];

s = 1;
img = ExampleData[{"TestImage", "Aerial"}];
Manipulate[
 {s, ImageResize[img, Scaled[s]]},
 {t, 1/2, 2}]

I would pick a different character than "." perhaps. The user cannot enter in a period or Dot. For instance the following works for Control+Option+. on a Mac:

SetOptions[EvaluationNotebook[], 
  NotebookEventActions -> {
    {"KeyDown", "."} :> If[CurrentValue["ControlKey"], (s = 0.9 s)], 
    PassEventsDown :> ! CurrentValue["ControlKey"]}];

Typing a regular . and a Control+. are processed as normal, and Option+. becomes \[GreaterEqual] also like normal. This has to do, I assume, with precedence of menu actions over notebook events and how keyboard typing is translated into key-down events.


Update

One could also use CellEventActions. For this to work, you have to click in the output cell.

CellPrint[
 ExpressionCell[
  Manipulate[{s, ImageResize[img, Scaled[s]]}, {t, 1/2, 2}],
  "Output",
  CellEventActions -> {
    {"KeyDown", "."} :> (s = 0.9 s)}
  ]
 ]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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