I’m in the beginning stages of a project and am currently building motor templates. Each template has the following custom properties:
running_color (color)
stopped_color (color)
alarm_color (color)
running_indication (Boolean)
alarm_indication (Boolean)
I would like to know how I could use the Boolean “alarm_indication” to cause the motor’s “Stroke style” to increase to a width of 5.
As far as I can see this is not possible with binding - you’ll have to use Python to do this. The information about setting stroke style in code came from tebright1’s post here.
Right click on the background of your motor template and select ‘Scripting’
Select the propertyChange / propertyChange event
Enter the following code:
if event.propertyName == 'alarm_indication':
from java.awt import BasicStroke
rectangle = event.source.getComponent('Rectangle')
if event.newValue == 1:
rectangle.strokeStyle = BasicStroke(5)
else:
rectangle.strokeStyle = BasicStroke(1)
You will obviously have to change what object you are getting a reference for. Mine is called ‘Rectangle’. Your motor might consist of a number of shapes - you’ll have to set the strokeStyle for all the ones you want to increase in width.
[quote=“AlThePal”]What would the given example look like using objectScript() Phil?[/quote]First, you’d create a project or shared script that converts a boolean to a stroke:from java.awt import BasicStroke
def alarmStroke(thick):
return BasicStroke(5) if thick else BasicStroke(1)Then call it from the binding expression with the boolean as an extra argument:objectScript('project.stroke.alarmStroke(args[0])', {Root Container.alarm_indication})Note that arguments after the string of code are presented as a tuple named ‘args’.
The other major advantage of this approach is it always runs – no need to switch the designer to preview mode.
Unfortunately, runScript() can only pass arguments when the expression string is a function name. I often want to use one-liners for extra functionality. Say one rectangle needs a different alarm thickness – with objectScript, you can put that customization right in the expression:objectScript('project.stroke.BasicStroke(10) if args[0] else project.stroke.BasicStroke(1)',
{Root Container.alarm_indication})Note that java.awt.BasicStroke was imported into project.stroke, so it’s available to Ignition scripts with no further import.
Just for completeness, here’s how you do this with runScript and Custom Methods on templates:
Create a template e.g. Test
Create an alarm_indication Template Parameter on the template
Put a custom method on the root of the template:
def setBorderStyle(self, alarm_indication):
from java.awt import BasicStroke
return BasicStroke(5) if alarm_indication else BasicStroke(1)
4. Put the following expression on the Stroke Style of the object you wish to animate:
Note the path to access the template root’s custom method from the object. Putting the custom method on the object itself and using a path of self.setBorderStyle works with objects on windows but not with templates.
As Phil points out in the following discussion, this form of the code is faster: runScript('self.parent.setBorderStyle', 0, {Test.alarm_indication})
[quote=“AlThePal”]runScript('self.parent.setBorderStyle(' + {Test.alarm_indication} + ')', 0)[/quote]You can do this, but it won’t scale. Changing the executable string that runScript uses (or objectScript) will increase the execution time by a couple orders of magnitude. I’ve seen tens of milliseconds vs. hundreds of microseconds in typical cases. Don’t make jython compile things on the fly. That’s why argument passing is so important.
[quote=“AlThePal”]How can you tell how long this is taking?[/quote]I instrumented objectScript() and view() while I developed them. Getting rid of jython compiler overhead wasn’t the original motivator for these functions, but that objective was quickly added. Oh, and the instrumentation is still present in the view() function and can be displayed by setting its logger to DEBUG mode.