PopupWindow objects can be clicked multiple times, opening multiple popup windows for the same object. How can I prevent this?

A bit more detail: I have an application which displays a graphic. The user can click on elements of the graphic to call up an information panel about that element using PopupWindow. The user might have several of these popups open at once. To prevent confusion, I would like to make sure that the user cannot open more than one popup per object. I can't see a straightforward approach to doing this, so I'm hoping for some ideas from this fine community.

Example code:

DynamicModule[{col = ConstantArray[Blue, 5]},
 Graphics[{Table[With[{i = i},
       col[[i]] = If[CurrentValue["MouseOver"], Red, Blue];
       {Dynamic@col[[i]], Disk[{i, 0}, 0.5]}],
       col[[i]] = If[CurrentValue["MouseOver"], Red, Blue];
       Framed[Style["Disk " <> ToString[i], White, 20], 
        FrameMargins -> 80, Background -> Dynamic@col[[i]]]], 
      WindowSize -> 280]
     ], {i, 5}]}]]

Here I have clicked on disk 4 twice, opening a duplicate of the information window. I want to prevent that:

enter image description here

  • $\begingroup$ Only idea I have is: You could give each PopupWindow title and then check every Notebooks[] every second or so to close duplicates? $\endgroup$ – Ajasja Oct 30 '12 at 11:57
  • $\begingroup$ You can define an index list for windows e.g. from 1 to 5. Before opening a window check if the index is still there in the list then remove the index and open the window else do nothing. $\endgroup$ – s.s.o Oct 30 '12 at 13:11
  • $\begingroup$ I don't think you can do that with PopoupWindow[], because once issued it will ever bring up a window with the specified contents. You can, however, create a notebook if it hasn't been created yet. You may use FE`Evaluate[FEPrivate`GetPopupList["MenuListWindows"]] to check the currently active notebooks. $\endgroup$ – Dr. belisarius Oct 30 '12 at 13:20
  • $\begingroup$ @belisarius, thanks. I'm not clear on what your code snippet gives that Notebooks[] doesn't? $\endgroup$ – Simon Woods Oct 30 '12 at 21:01
  • 1
    $\begingroup$ @YvesKlett, yes that's normal. You can change the behaviour with WindowFloating->False. $\endgroup$ – Simon Woods Oct 31 '12 at 8:58

The PopupWindow object is nothing more than a Button with a CreateDocument action:

PopupWindow[a, b] // InputForm

(* Button[a, CreateDocument[Internal`PopupWindowNotebook[b]], 
Appearance -> None, BaseStyle -> {}, DefaultBaseStyle -> {}] *)

Since CreateDocument returns a notebook object which can be assigned to a symbol, it is simple to check if there is an already open popup window. By inserting this check into the Button code, the desired behaviour is obtained:

singlePopup[pw_] := With[{p = Unique["popup"]},
  pw /. Button[a_, b_, c___] :>
    Button[a, If[! ValueQ[p] || Options[p] == $Failed, p = b], c]]

(* e.g. *) PopupWindow["Click here", "You clicked!"] // singlePopup
| improve this answer | |
  • $\begingroup$ Very nice, a big +1 $\endgroup$ – Dr. belisarius Oct 30 '12 at 23:36
  • $\begingroup$ V11.3 appears to have broken this, so after poping up and then closing, you can no longer popup again. $\endgroup$ – DrBubbles Mar 15 '18 at 15:27
  • $\begingroup$ According to Wolfram support this is a bug and will be fixed in a future release. Options[NotebookObject["bad"]] will return an empty List, {}, instead of \$Failed. Support provided a workaround: Add Options[p] == {} to your If statement: singlePopup[pw_] := With[{p = Unique["popup"]}, pw /. Button[a_, b_, c___] :> Button[a, If[! ValueQ[p] || Options[p] == {} || Options[p] == $Failed, p = b], c]] $\endgroup$ – DrBubbles Mar 20 '18 at 14:45
  • $\begingroup$ @DrBubbles, thanks for the update. I actually ran across this today and changed Options to NotebookInformation which also worked. $\endgroup$ – Simon Woods Mar 20 '18 at 20:39

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.