Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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]]
share|improve this question
1  
related –  bobthechemist Jun 23 at 23:12
1  
It works quite smooth for me, the problem is that it loses the focus, isn't it? –  Kuba Jun 23 at 23:34
    
@Kuba. what you report is my experience, too. –  m_goldberg Jun 23 at 23:40
    
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. –  m_goldberg Jun 24 at 2:14
    
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. –  Putterboy Jun 24 at 11:06

2 Answers 2

up vote 7 down vote accepted

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.

share|improve this answer
    
That's way better ;) –  Öskå Jun 24 at 14:42
    
Well done. I messed with this for some time, but failed to come up with anything nearly so good as this. –  m_goldberg Jun 24 at 15:38
    
And further, I would call this a solution, not a work-around (or a "walk-around" as you call it :). –  m_goldberg Jun 24 at 15:42
    
@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? –  Putterboy Jun 24 at 16:00
    
@m_goldberg You are probably right, thanks for the edit. :) –  Kuba Jun 24 at 16:06

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]]
share|improve this answer
    
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. –  Putterboy Jun 24 at 17:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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