10

Is there a way to detect double click events? I did not find anything on the doc page of EventHandler.

Use case: I want to re-implement the Crop Image... functionality available form the context menu when clicking images. The cropping GUI appears much too slowly with even moderately large images, such as screenshots of the full screen. Although I could use a button to crop, I'd prefer using double click, just like in the original implementation.

István Zachar
  • 47,032
  • 20
  • 143
  • 291
Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263

2 Answers2

14

You can use a combination of MouseDown and MouseClickCount as in the following examples:

example 1: double-click increments the value of j:

j = 1; EventHandler[Panel[Dynamic[j]], 
"MouseDown" :> If[CurrentValue["MouseClickCount"] == 2, ++j]]

example 2: double-click toggles the text color:

DynamicModule[{col = Green}, 
  EventHandler[
    Style["text", FontColor -> Dynamic[col]], 
   {"MouseDown" :> 
      If[CurrentValue["MouseClickCount"] == 2, 
         (col = col /. {Red -> Green, Green -> Red})]}
  ]]
Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
kglr
  • 394,356
  • 18
  • 477
  • 896
  • This seems to be the "right" solution (the one that uses the system's double click delay). @MrWizard is it available in v7 as well (I'd like to make the application work in 7)? – Szabolcs Mar 13 '12 at 10:04
  • @Szabolcs yes it is! +1 kguler – Mr.Wizard Mar 13 '12 at 10:07
  • @Szabolcs one point regarding this method: if I double-click repeatedly is does not register (the text color does not change repeatedly). This is different from typical Windows behavior. – Mr.Wizard Mar 13 '12 at 10:25
  • @Mr.Wizard That's easy to fix with Mod[..., 2] == 0. Actually it does register repeated double clicks (with a pause inbetween), but not a quadruple click. Some programs (e.g. browsers and word processors) register triple or even quadruple clicks as well. Try many clicks in Firefox. First it selects the word, then paragraph, then word again. A separate click clear the selection. This method makes it easy to implement those behaviours (not that I want to). – Szabolcs Mar 13 '12 at 10:37
3

You could do something like this:

DynamicModule[{col = Green, time = AbsoluteTime[]}, 
  EventHandler[
    Style["text", FontColor -> Dynamic[col]],
    "MouseClicked" :> 
      If[AbsoluteTime[] - time > 0.25, 
         time = AbsoluteTime[],
         col = col /. {Red -> Green, Green -> Red}]
  ]]

Implementing limited tolerance for mouse position will be more complicated.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • It is definitely possible to do something like this, but if it's the only solution, I'd prefer not to use double clicks at all. I was hoping there is a solution that integrates with the system's double click detection and obeys the system-wide settings for it (e.g. maximum time and distance between clicks). BTW I didn't do much GUI programming, so I am now sure how big a problem it is to differentiate between double clicks and single clicks without causing a delay in the interpretation of single clicks. I'm curious if this requires special attention when using ... – Szabolcs Mar 13 '12 at 07:03
  • ... common GUI toolkits. I was trying to figure out how the built-in image cropping GUI does it, but it's not trivial to get it (converting to InputForm strips most of the GUI code). I'm not sure if that functionality is available in version 7. – Szabolcs Mar 13 '12 at 07:04
  • @Szabolcs "I am now sure how big a problem it is to differentiate between double clicks and single clicks without causing a delay in the interpretation of single clicks." -- perhaps I am missing something, but isn't a delay of at least the double-click detention window necessary for single-click action? At least I cannot recall an exception to this in Windows. – Mr.Wizard Mar 13 '12 at 07:08
  • I really don't know how these work :) I thought that maybe the delay is not there when no special double click actions are available for some GUI object. I have no idea how noticeable such a short delay would be, for example when clicking a button and waiting for an immediate response. – Szabolcs Mar 13 '12 at 07:10
  • Some spelunking results: It seems that the image cropper is based on a special box type, Image`InteractiveImageCropBoxes, and is not implemented in terms of standard and documented things. – Szabolcs Mar 13 '12 at 07:14
  • @Szabolcs I thought it would be clear that there should be no delay on single-click events if a double-click action is not defined. In all cases where both actions are possible (renaming or opening a file on Windows) I recall a delay. I cannot see how it would work otherwise, unless you were to start the single-click action, and then immediately revert if a second click falls within the double-click window. – Mr.Wizard Mar 13 '12 at 07:15
  • @Mr.Wizard: On Windows, a window gets multiple messages for a double click: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK, and WM_LBUTTONUP. Some applications choose to delay handling the WM_LBUTTONDOWN message, some don't. For example, if you click a word in most text editors, the cursor will be positioned there immediately. If you double click, the whole word will be selected. – Niki Estner Mar 13 '12 at 13:13
  • @nikie good counter-example (and implementation note). Thank you. – Mr.Wizard Mar 13 '12 at 13:19