Lets say I select shapes in a Graphics diagram in the following picture.

enter image description here

Generated from the following set of code:

   (* Write Triangle *)
    PolygonBox[{{-1, 0}, {1, 1}, {1, -1}}]
   , UpdateInterval -> 1]]
  CircleBox[{0, 0}], CircleBox[{0, 0}],
  CircleBox[{1, 1 }], CircleBox[{1, 1 }],
  Rectangle[{0, -1}, {2, 1}], Rectangle[{0, -1}, {2, 1}]
  }, ImageSize -> {55, 55}]

Now if I press NotebookWrite it replaces {CircleBox[{0,0}],RectangleBox[{0,-1}]} with a Triangle.

enter image description here

My question: Is there a way to replace each shape (CircleBox[{0,0}] and RectangleBox[{0,-1}]) with separate objects instead of replacing both with one object?

  • $\begingroup$ it seems to me your Button doesn't work replacing selections, it just adds the triangle (I get the graphics like your). This could be due to the NotebookWrite that doesn't recognize the selection inside the Graphics. Did it works for you? What do you really need to do? Replace a part inside a graphics, by selecting it with the mouse? Perhaps working with ReplaceAll on the Graphics' structure could be easier. $\endgroup$
    – bobknight
    Commented Jul 23, 2013 at 16:47
  • $\begingroup$ @bobknight Notice there are two objects in the graphics (CircleBox and Rectangle). In fact there are duplicate objects for every object. I put duplicate objects to insure nobody attempted to simple search and replace the graphic as you briefly discussed. $\endgroup$
    – William
    Commented Jul 23, 2013 at 17:07

1 Answer 1


Yes, I have seen it works but sometimes seems to have problems recognizing the right selection. An example of a raw solution could be

    gr = Graphics[{CircleBox[{0, 0}], CircleBox[{0, 0}], 
    CircleBox[{1, 1}], CircleBox[{1, 1}], 
    RectangleBox[{0, -1}, {2, 1}], RectangleBox[{0, -1}, {2, 1}]}];
Panel[Column[{Row[{"Current selection ", 
       UpdateInterval -> 0]]}], 
    With[{selection = NotebookRead[InputNotebook[]]}, 
     gr = ReplaceAll[gr, 
       MapThread[#1 :> #2 &, {selection, {{Red, 
           Polygon[{{-1, 0}, {1, 1}, {1, -1}}]}, {Blue, 
           Polygon[{{0, 0}, {1, 2}, {2, 0}}]}}}]]], 
    ImageSize -> Automatic], Spacer[10], Dynamic[gr]}]]

I just deleted the ImageSize because it was too small to work with my (old) mouse. Then added a Panel to control everything together. Here the problem is that the second argument of the MapThread is a fix list of two Polygon, so it works only when you select two elements from the original graphics. According to what you really need, there you can have a custom list of objects, depending on the length of the current selection inside the Graphics. Thre was an error in the first code, Rectangle instead of RectangleBox so it was not replaced. Moreover I added the color to each Polygon. The problem still not dealt with is the replacement of "all" objects with the same structure made by ReplaceAll, but here is not clear to me if you want or not such behavior. For instance when you select the CircleBox[{1,1}] then click the button, you want both CircleBox[{1,1}] replaced by the Polygon or just that selected? This latter can be achieved with some further code.

  • $\begingroup$ Correct me if I am wrong, but it appears by using your code it is impossible to tell which of 2 identical shapes you are replacing. This is important if u ever choose to add a EventHandler or add Colors which wraps identical but does distinguish the fuctionality and appereance of the 2 shapes. $\endgroup$
    – William
    Commented Jul 23, 2013 at 17:58
  • $\begingroup$ Not sure I understand what you mean, however you can do whatever you need in the MapThread, meaning that you can add code to check which shapes are currently selected (working on NotebookRead[InputNotebook[]]) and create any replacement object by working on the second argument (where I just put two identical Polygon). It depends on what you really need to do. $\endgroup$
    – bobknight
    Commented Jul 23, 2013 at 18:30
  • $\begingroup$ That is what I am saying. There is no way using your code to determine what element is selected because EventHandler isnt selected when you select and object. Meaning two objects in the same location will look the same. $\endgroup$
    – William
    Commented Jul 23, 2013 at 20:12
  • 2
    $\begingroup$ but I guess there is a way to discover which one is selected. If the graphics is not manually managed, the order of objects follows the order in the argument list. In other words, the foremost is the last in the Graphics' list. An example Graphics[{Red, Circle[], Blue, Circle[]}], you see the blue one and when acting with the mouse you will surely select the blue one. So, even without color, you can be sure the selected is the latest in the list. $\endgroup$
    – bobknight
    Commented Jul 23, 2013 at 20:28
  • $\begingroup$ I hadn't thought of that. Probably works most of the time. It seems like there still might be some age case issues if a user moves the object on top of another object while working. $\endgroup$
    – William
    Commented Jul 23, 2013 at 20:36

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.