7
$\begingroup$

I am experimenting to use MouseDragged eventhandler to change the vertices positions of a triangle, it works, but not as smooth as using Locators. Is this the correct way to handle mouse dragging? Would someone please help to improve the response speed.

DynamicModule[{ pos1 = {1, 0}/2 , pos2 = {1, 1}/2 , pos3 = {-1, 0}/2},
 edglst = { 1 <-> 2 , 2 <-> 3 , 3 <-> 1   };
  Dynamic@Graph[
   { EventHandler[1, {"MouseDragged" :> (pos1 = MousePosition["Graphics"])}],
     EventHandler[2, {"MouseDragged" :> (pos2 = MousePosition["Graphics"])}], 
     EventHandler[3, {"MouseDragged" :> (pos3 = MousePosition["Graphics"])}]} ,
   edglst,
   VertexCoordinates -> {pos1, pos2, pos3 } ,
   VertexSize -> 0.08, VertexLabels -> "Name",
   PlotRange -> 1, EdgeStyle -> {Thick}, ImagePadding -> 10]]
$\endgroup$
6
  • 1
    $\begingroup$ related $\endgroup$ Commented Jun 23, 2014 at 23:12
  • 1
    $\begingroup$ It works quite smooth for me, the problem is that it loses the focus, isn't it? $\endgroup$
    – Kuba
    Commented Jun 23, 2014 at 23:34
  • $\begingroup$ @Kuba. what you report is my experience, too. $\endgroup$
    – m_goldberg
    Commented Jun 23, 2014 at 23:40
  • $\begingroup$ This is a tough problem. I've made some minor improvements to the OP's code, but nothing dramatic enough to be worth posting. I have found, after playing with this problem for a while, that my dragging skills have improved to the point where I only infrequently loose a vertex as I drag it around. $\endgroup$
    – m_goldberg
    Commented Jun 24, 2014 at 2:14
  • $\begingroup$ The vertex does follow the mouse nicely if the mouse motion is slow enough, but the vertex just stop behind when the mouse moves in normal speed. Locator doesn't have such problem. $\endgroup$
    – Putterboy
    Commented Jun 24, 2014 at 11:06

2 Answers 2

8
$\begingroup$

The reason for this behaviour is that as soon as the cursor gets away from a particular vertex marker it leaves the associated EventHandler.

Here's a work-around, let's associate the event handler with the whole Graph. We just need to take care of updating the proper pos.

 DynamicModule[{ind = 1, pos1 = {1, 0}/2, pos2 = {1, 1}/2, pos3 = {-1, 0}/2},
                   edglst = {1 <-> 2, 2 <-> 3, 3 <-> 1};
 EventHandler[
  Dynamic @ Graph[{1, 2, 3}, edglst, VertexCoordinates -> {pos1, pos2, pos3}, 
                  VertexSize -> 0.08, VertexLabels -> "Name", PlotRange -> 1, 
                  EdgeStyle -> {Thick}, ImagePadding -> 10, Frame -> True],

  {"MouseDown" :> With[{set = {pos1, pos2, pos3}, pos = MousePosition["Graphics"]},
                       ind = Position[set, Nearest[set, pos][[1]]][[1, 1]]],       
   "MouseDragged" :> (ReleaseHold[Hold[Set][Hold[{pos1, pos2, pos3}][[{1}, ind]], 
                                            MousePosition["Graphics"]]])},
   PassEventsDown -> True]]

enter image description here

Notice that inner EventHandlers are not needed now but you can add them with any additional procedures you need. For this purpose I've left PassEventsDown-True.

$\endgroup$
9
  • $\begingroup$ That's way better ;) $\endgroup$
    – Öskå
    Commented Jun 24, 2014 at 14:42
  • $\begingroup$ Well done. I messed with this for some time, but failed to come up with anything nearly so good as this. $\endgroup$
    – m_goldberg
    Commented Jun 24, 2014 at 15:38
  • $\begingroup$ And further, I would call this a solution, not a work-around (or a "walk-around" as you call it :). $\endgroup$
    – m_goldberg
    Commented Jun 24, 2014 at 15:42
  • $\begingroup$ @Kuba It is really cool, thanks a lot! But it is hard for me to see through the tricks behind the code:"MouseDragged" :> ( ReleaseHold[ Hold[Set] [ Hold[{pos1, pos2, pos3}][[ {1}, ind ]], MousePosition["Graphics"] ](* Hold ) ]( ReleaseHold *) ) Would you please give some explanations on it? $\endgroup$
    – Putterboy
    Commented Jun 24, 2014 at 16:00
  • $\begingroup$ @m_goldberg You are probably right, thanks for the edit. :) $\endgroup$
    – Kuba
    Commented Jun 24, 2014 at 16:06
7
$\begingroup$

Kuba's answer is brilliant, but it has a rather ugly bit in it with a lot of unnecessary fooling around with Hold and ReleaseHold in order to make assignment to variables. As is so often the case with Mathematica, this fooling around with variables can be eliminated by working with a list, so I have reworked Kuba's answer to keep the vertex coordinates in a list. That makes the mouse drag action simple because there in no need make assignments to variables.

DynamicModule[{index = 1, vertxCoords = {{1., 0.}/2, {1., 1.}/2, {-1., 0.}/2}},
  EventHandler[
    Dynamic@Graph[{1, 2, 3}, {1 <-> 2, 2 <-> 3, 3 <-> 1}, 
      VertexCoordinates -> vertxCoords,
      VertexSize -> {.04, .04},
      VertexLabels -> "Name",
      PlotRange -> 1,
      EdgeStyle -> Thick,
      ImagePadding -> 10,
      Frame -> True],
    {"MouseDown" :>
      With[{p = MousePosition["Graphics"]}, 
        index = Position[vertxCoords, Nearest[vertxCoords, p][[1]]][[1, 1]]], 
     "MouseDragged" :> (vertxCoords[[index]] = MousePosition["Graphics"])},
    PassEventsDown -> True]]
$\endgroup$
1
  • $\begingroup$ Thanks a lot. So the reason for this problem is because of getting lost of focus as pointed out by Kuba previously. And it is not a good practice to set the Eventhandlers on the tiny individual vertices on this purpose. $\endgroup$
    – Putterboy
    Commented Jun 24, 2014 at 17:34

Your Answer

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

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