# Add script to dynamically created objects

**URL:** <https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215>\
**Category:** General Discussion\
**Tags:** vision\
**Created:** [September 19, 2022, 7:20am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215 "2022-09-19T07:20:59Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![R\_P](https://avatars.discourse-cdn.com/v4/letter/r/aca169/32.png) [@R\_P](https://forum.inductiveautomation.com/u/R_P)\
**Post date:** [September 19, 2022, 7:20am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/1 "2022-09-19T07:20:59Z")

</div>

Hi.  
We are creating rectangle dynamically on vision client by button script and works fine.  
We want to drag and drop that rectangle using Mouse Motion - Mouse Dragged script.  
its works fine if we manually add script to that rectangle in design mode.  
We are looking for to add Mouse Motion - Mouse Dragged script automatically to rectangle when we are creating rectangle dynamically on vision client by button  
Not: Rectangles are created dynamically by sequence 1st click - Rectangle, 2nd Click- Rectangle1, Rectangle2…so on

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 19, 2022, 8:09am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/2 "2022-09-19T08:09:47Z")

</div>

This is an interesting idea. What is your code for dynamically creating the rectangles?

---

<div class="post-metadata">

**Author:** ![R\_P](https://avatars.discourse-cdn.com/v4/letter/r/aca169/32.png) [@R\_P](https://forum.inductiveautomation.com/u/R_P)\
**Post date:** [September 19, 2022, 8:10am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/3 "2022-09-19T08:10:49Z")

</div>

from com.inductiveautomation.factorypmi.application.components import PMIRectangle

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 19, 2022, 9:21am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/4 "2022-09-19T09:21:15Z")

</div>

When I move shapes around dynamically in Vision, I usually do it with  
`system.gui.transform(componentName, newX, newY)`

---

<div class="post-metadata">

**Author:** ![R\_P](https://avatars.discourse-cdn.com/v4/letter/r/aca169/32.png) [@R\_P](https://forum.inductiveautomation.com/u/R_P)\
**Post date:** [September 19, 2022, 10:00am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/5 "2022-09-19T10:00:40Z")

</div>

Thanks…how can i add above script to rectangle…i create rectangle by button click and same time time i want to attached dragged event script to rectangle by writting script in button event itself

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 19, 2022, 10:55am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/6 "2022-09-19T10:55:34Z")

</div>

If you are dragging the rectangle, then this will need to be done from the onMouseDragged event handler

---

<div class="post-metadata">

**Author:** ![R\_P](https://avatars.discourse-cdn.com/v4/letter/r/aca169/32.png) [@R\_P](https://forum.inductiveautomation.com/u/R_P)\
**Post date:** [September 19, 2022, 11:24am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/7 "2022-09-19T11:24:52Z")

</div>

Thanks… i want to add script under onMouseDragged event in Rectangle component from outside. Once i create rectangle dynamically on vision client then i cant go back in designer and add mouse dragged event script manually

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 19, 2022, 11:40am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/8 "2022-09-19T11:40:49Z")

</div>

You will have to make the component name in your script a variable, and determine which object to pass into the script based on the current positions of the rectangles relative to the mouse pointer during the mousePressed event. If two rectangles are overlapping, you will have to find a way to get the z order of the dynamically created objects.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 19, 2022, 11:47am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/9 "2022-09-19T11:47:15Z")

</div>

You could probably create a custom property to hold onto the variable name until the mouseReleased event. Please note that I have never attempted anything like what you are doing in ignition. These are just my ideas on how to go about it.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [September 19, 2022, 3:41pm UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/10 "2022-09-19T15:41:48Z")

</div>

I can’t imagine adding new components in this way to actually be easier than using e.g. the Paintable Canvas and just doing all the work yourself.

I would just construct a dataset with four columns - `x1, y1, x2, y2` and add new points to it at runtime. A mouse event handler on the canvas could easily loop through the dataset, checking bounding boxes, and determine if an event is inside of a rectangle.

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 20, 2022, 11:28am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/11 "2022-09-20T11:28:46Z")

</div>

Okay, so I had the night off, and I since I was [inadvertently] given credit for having solved this one, I figured I would go ahead and take a crack at it. Plus, I found this challenge interesting. Here is the solution I came up with:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/7/47aed2c377076999d05a1f6cb5eb41ceb441033f.png)

First, I used a paintable canvas and added a dataset custom property named rectangles with all of the parameters I believed I would need to keep track of: keyIndex, name, x, y, width, height, and zOrder

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/2/1/21c4ec5b629e61eeb3c248798995c22b211a06e5.png)

Then, I added two additional custom properties for tracking rectangle selection: currentKeyIndex and currentRectangle:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/b/f/bf09583f25bf68ada0604f63644a5d3d1bfc77c4.png)

I used a simple button to create the rectangles using this script on the actionPerformed event handler:

```auto
rectangles = event.source.parent.getComponent('Paintable Canvas').rectangles
keyIndex = rectangles.rowCount
name = "rectangle"+str(keyIndex)
x = 10
y = 200
width = 100
height = 100
zOrder = 1
newRectangle = [keyIndex, name, x, y, width, height, zOrder]
for rectangle in range(rectangles.rowCount):
	rectangles = event.source.parent.getComponent('Paintable Canvas').rectangles
	rectangleIndex = rectangles.getValueAt(rectangle, "keyIndex")
	zOrder = rectangles.getValueAt(rectangle, "zOrder")
	newZOrder = zOrder+1
	zOrderChange = system.dataset.updateRow(rectangles, rectangleIndex, {"zOrder":newZOrder})
	event.source.parent.getComponent('Paintable Canvas').rectangles = zOrderChange
rectangles = event.source.parent.getComponent('Paintable Canvas').rectangles
updatedRectangles = system.dataset.addRow(rectangles, keyIndex, newRectangle)
event.source.parent.getComponent('Paintable Canvas').rectangles = updatedRectangles

```

The script loads the default parameters for the new rectangle, giving the new rectangle the lowest zOrder. It then loops through all of the other rectangles and increments their zOrders accordingly.

To drag a rectangle, I developed a script for rectangle selection using the mousePressed event handler. It loops through all of the rectangles and builds a list of all rectangles that are underneath the mouse pointer. It then loops through that sublist to determine which rectangle has the lowest zOrder. Finally, it gives the selected rectangle a zOrder of one and updates all of the zOrders accordingly. Here is the code:

```auto
rectangles = event.source.rectangles
rectanglesInRange = []
currentRectangle = "noneSelected"
currentKeyIndex = None
lowestZOrder = rectangles.rowCount
e = event
for rectangle in range(rectangles.rowCount):
	x1 = rectangles.getValueAt(rectangle, "x") 
	x2 = x1 + rectangles.getValueAt(rectangle, "width")
	y1 = rectangles.getValueAt(rectangle, "y") 	
	y2 = y1 + rectangles.getValueAt(rectangle, "height")
	if e.x > x1 and e.x < x2 and e.y > y1 and e.y < y2:
		rectanglesInRange.append(rectangles.getValueAt(rectangle, "keyIndex"))
if len(rectanglesInRange) > 0:
	for rectangle, keyIndex in enumerate(rectanglesInRange):
		zOrder = rectangles.getValueAt(keyIndex, "zOrder")
		if zOrder <= lowestZOrder:
			lowestZOrder = zOrder
			currentRectangle = rectangles.getValueAt(keyIndex, "name")
			currentKeyIndex = rectangles.getValueAt(keyIndex, "keyIndex")
	for rectangle in range(rectangles.rowCount):
		rectangles = event.source.rectangles
		zOrder = rectangles.getValueAt(rectangle, "zOrder")
		if zOrder == lowestZOrder:
			zOrderChange = system.dataset.updateRow(rectangles, rectangle, {"zOrder":1})
			event.source.rectangles = zOrderChange
		elif zOrder < lowestZOrder:
			zOrderChange = system.dataset.updateRow(rectangles, rectangle, {"zOrder":(zOrder+1)})
			event.source.rectangles = zOrderChange
event.source.currentRectangle = currentRectangle
event.source.currentKeyIndex = currentKeyIndex

```

To move the rectangles, using the mouseDragged event handler, I simply offset the mouse cursor position by half the length and width of the rectangle, so the cursor remains centered on the rectangle. Then, I continuously update the dataset with the offset mouse cursor position. Here is the code:

```auto
currentRectangle = event.source.currentRectangle
keyIndex = event.source.currentKeyIndex
if currentRectangle != "noneSelected":
	rectangles = event.source.rectangles
	currentX = event.x - (.5*rectangles.getValueAt(keyIndex, "width"))
	currentY = event.y - (.5*rectangles.getValueAt(keyIndex, "height"))
	positionChange = system.dataset.updateRow(rectangles, keyIndex, {"x":currentX,"y":currentY})
	event.source.rectangles = positionChange

```

Finally, I remove the rectangle selection at the mouseReleased event. Here is that code:

```auto
event.source.currentRectangle = "noneSelected"
event.source.currentKeyIndex = None

```

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 20, 2022, 11:29am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/12 "2022-09-20T11:29:43Z")

</div>

Here is a video of the result:

[https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/c/cc36a3b15658efed84e81aa88d821e01a2599537.mp4](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/c/cc36a3b15658efed84e81aa88d821e01a2599537.mp4)

I almost forgot. To paint the rectangles, I developed this code that I used on the paintable canvas’s onPaint event handler:

```auto
from java.awt import Color
from java.awt.geom import Rectangle2D
rectangles = system.dataset.sort(event.source.rectangles, "zOrder", False)
for rectangle in range(event.source.rectangles.rowCount):
	keyIndex = rectangles.getValueAt(rectangle, "keyIndex") 
	x = rectangles.getValueAt(rectangle, "x") 
	y = rectangles.getValueAt(rectangle, "y") 	
	width = rectangles.getValueAt(rectangle, "width") 	
	height = rectangles.getValueAt(rectangle, "height") 	
	rectangle = Rectangle2D.Float( x, y, width, height)
	g = event.graphics
	if keyIndex % 10 == 0 or keyIndex % 10 == 5:
		g.setColor(Color.RED)
	elif keyIndex % 10 == 1 or keyIndex % 10 == 6:
		g.setColor(Color.BLUE)
	elif keyIndex % 10 == 2 or keyIndex % 10 == 7:
		g.setColor(Color.GREEN)
	elif keyIndex % 10 == 3 or keyIndex % 10 == 8:
		g.setColor(Color.YELLOW)
	else:
		g.setColor(Color.BLACK)
	g.fill(rectangle)

```

It sorts the dataset by descending zOrder, then loops through to paint all of the rectangles. I also added code that varies the color of the rectangles based upon the ones digit of the keyIndex, just to make the zOrder corrections more obvious.

Edit: Thanks @paul-griffith for the paintable canvas direction. I found it to be intuitive and easy to implement.

---

<div class="post-metadata">

**Author:** ![R\_P](https://avatars.discourse-cdn.com/v4/letter/r/aca169/32.png) [@R\_P](https://forum.inductiveautomation.com/u/R_P)\
**Post date:** [September 21, 2022, 4:40am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/13 "2022-09-21T04:40:26Z")

</div>

Thanks…Excellent

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [September 25, 2022, 2:15pm UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/14 "2022-09-25T14:15:55Z")

</div>

A message I received in response to this post indicated that I should clarify datatypes.

The paintable canvas custom property datatypes are as follows:

```auto
currentKeyIndex = Integer
currentRectangle = String
rectangles = Dataset

```

The rectangles dataset column datatypes are as follows:

```auto
keyIndex = Integer
name = String
x = Float
y = Float
width = Float
height = Float
zOrder = Integer

```

---

<div class="post-metadata">

**Author:** ![justinedwards.jle](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/justinedwards.jle/32/37854_2.png) [@justinedwards.jle](https://forum.inductiveautomation.com/u/justinedwards.jle)\
**Post date:** [October 7, 2022, 9:48am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/15 "2022-10-07T09:48:45Z")

</div>

Just for fun:

[https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/7/3721141dddede24014d9363eaba3f861f2a088bb.mp4](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/7/3721141dddede24014d9363eaba3f861f2a088bb.mp4)

---

<div class="post-metadata">

**Author:** ![R\_P](https://avatars.discourse-cdn.com/v4/letter/r/aca169/32.png) [@R\_P](https://forum.inductiveautomation.com/u/R_P)\
**Post date:** [October 7, 2022, 10:16am UTC](https://forum.inductiveautomation.com/t/add-script-to-dynamically-created-objects/64215/16 "2022-10-07T10:16:52Z")

</div>

Excellent
