createProperty when another is changed before simulation is running

Hi!

Trying to create properties when another property is changed. I got this to work so that when I start the simulation it creates those new properties. But I want to create those before I start the simulation so I can input values in them.

Now I have those like this

def OnRun():
  OutFeeds=comp.getProperty("numberOfOutFeeds")
  OutFeeds.OnChanged = showOutFeeds(OutFeeds.Value)

and

def showOutFeeds(value):
  print("Hello World")  
  comp=getComponent()  
  for i in range(value):
    comp.createProperty(VC_INTEGER, "OutX"+str(i+1))

and
image

Where should I put that OnChanged event so it would create those properties before starting simulation.
Additional question is how do I delete these code created properties when simulation is reseted?

Thank you so much!!

Hi Unnahi,

the line: OutFeeds.OnChanged = function() is off.
For events you do not exactly want to evaluate a function, but rather give it a function reference. For example

def OnRun():
  OutFeeds=comp.getProperty("numberOfOutFeeds")
  OutFeeds.OnChanged = showOutFeeds #this is now a function reference instead of evaluation

def showOutFeeds(*args):
  print(args)

If you want to toss in a parameter inside an event function, you can create an inline function and return a reference. Alternative options are to use global keyword.

def OnRun():
  OutFeeds=comp.getProperty("numberOfOutFeeds")
  OutFeeds.OnChanged = showOutFeeds(OutFeeds.Value)

def showOutFeeds(value):
  def InlineFun(*args)
    print("Hello World")  
    comp=getComponent()  
    for i in range(value):
      comp.createProperty(VC_INTEGER, "OutX"+str(i+1))
  return InlineFun

If you simply want to create some values before you start the simulation (so basically in def OnRun) you just write the snippet of code outside any function, making them global.

# write stuff here instead
# or here and then compile
# your OnChanged event doesn't really need to be inside OnRun function
# Just make sure that the OutFeeds is created before you access the event function.
def OnRun():
  OutFeeds=comp.getProperty("numberOfOutFeeds")
  OutFeeds.OnChanged = showOutFeeds(OutFeeds.Value)

Thanks @Lefa!

now I’m running into next problem

File “ComponentMover::PythonScript”, line 10, in showOutFeeds
TypeError: int() argument must be a string or a number, not ‘vcProperty’

when I compile the code it works fine. And prints number which is in numberOfOutfeeds property but when i change the value in the property it says that error above. I’ve tried to force it to integer but not working.

Hey,

How did you create the property “numberOfOutFeeds” in the first place? If you did it via modelling tab and created an integer type property as seen in figure 1, you should be fine. Otherwise I’d need a bit more extra info.

image
Figure 1

From the looks of it you’re trying to create multiple properties through your for i in range(value) loop. Properties are created ONCE and if you want to modify it, it’s better to just delete it and re-create. From the looks of it the loop attempts to create properties that take integers in, and the name is OutX1, OutX2… and so on.

I think you want to create ONE property that has multiple stepvalues, instead of multiple properties with different names.

Also please note that createProperty returns a vcProperty.

I also cannot replicate your issue. Figure 2 shows this.


Figure 2

Thank you @Lefa for your help!

I’ll let this sit for the weekend and will be back on this matter on monday. Mabe with fresher thoughts and brains :sweat_smile:

Have a great weekend!

P.S Yes I’ve created it form the properties menu and I’m trying to make multiple outfeed positions. So when the user gives the number of out feeds it creates properties for those outfeeds so the user can feed the x and y coordinates where those are in the warehouse.

I’m making an warehouse initial inventory creator and this is for that.

The basic idea is to check whether the property already exists, if it does → skip. If it does not → create it.

But do have a great weekend. I hope freshening up will help you finish the idea.

Thank’s for your help @lefa got it working!

Do you know why it needs that Inline Function to work?

Because you’re evaluating a function on an event.

prop.myEvent = yourFunction
vs.
prop.myEvent = yourFunction()

The lower one evaluates the function (runs it) while the top one gives it a function reference. Events need function reference which is why I made Inline function which is returned as a function reference.

The more “normal” way of doing it here would be to get the property as a global variable.
The code “could” look something like this…

comp = getComponent()
OutFeeds = comp.getProperty("numberOfOutFeeds")
val = OutFeeds.Value

def showOutFeeds(*args)
  global val
  # rest of your code

def OnRun():
  global val
  val = OutFeeds.Value
  OutFeeds.OnChanged = showOutFeeds

This way there is no need for Inline function.

Thanks again @Lefa !

I realized that I need to read the value when it is changed so I did it like this

def showOutFeeds():  
  def InLineFun(*args):
    value=comp.getProperty("numberOfOutFeeds").Value
    for i in range(10):
      propX=comp.getProperty("Out"+str(i+1)+" X")
      propY=comp.getProperty("Out"+str(i+1)+" Y")
      if propX:
        comp.deleteProperty("Out"+str(i+1)+" X")
      if propY:
        comp.deleteProperty("Out"+str(i+1)+" Y")
    for i in range(value):
      propX=comp.getProperty("Out"+str(i+1)+" X")
      propY=comp.getProperty("Out"+str(i+1)+" Y")  
      if not propX:
        comp.createProperty(VC_INTEGER, ("Out"+str(i+1)+" X"))
        comp.getProperty("Out"+str(i+1)+" X").WritableWhenSimulating=False        
      if not propY:
        comp.createProperty(VC_INTEGER, ("Out"+str(i+1)+" Y"))
        comp.getProperty("Out"+str(i+1)+" Y").WritableWhenSimulating=False
  return InLineFun
  
OutFeeds=comp.getProperty("numberOfOutFeeds")
OutFeeds.OnChanged =showOutFeeds()

This way got it to work as planned.

Great to hear that it works.

In this case you can just delete the InLineFun and make it look like this…

def showOutFeeds(*args):  
    value=comp.getProperty("numberOfOutFeeds").Value
    for i in range(10):
      propX=comp.getProperty("Out"+str(i+1)+" X")
      propY=comp.getProperty("Out"+str(i+1)+" Y")
      if propX:
        comp.deleteProperty("Out"+str(i+1)+" X")
      if propY:
        comp.deleteProperty("Out"+str(i+1)+" Y")
    for i in range(value):
      propX=comp.getProperty("Out"+str(i+1)+" X")
      propY=comp.getProperty("Out"+str(i+1)+" Y")  
      if not propX:
        comp.createProperty(VC_INTEGER, ("Out"+str(i+1)+" X"))
        comp.getProperty("Out"+str(i+1)+" X").WritableWhenSimulating=False        
      if not propY:
        comp.createProperty(VC_INTEGER, ("Out"+str(i+1)+" Y"))
        comp.getProperty("Out"+str(i+1)+" Y").WritableWhenSimulating=False

OutFeeds=comp.getProperty("numberOfOutFeeds")
OutFeeds.OnChanged =showOutFeeds

(please check the tabulation)