Animating the Paintable Canvas

Ok, day 3 of my introduction to Ignition and I discovered Paintable Canvas. Very cool and I see the power, I even made a pretty cool pump graphic of my own but it is time to animate.

In the repaint script I created a couple of variables that I use for the GradientPaint.

drkgrad = Color(27,148,31)
ltgrad = Color(216,255,234)

I have created dynamic properties for “Run” and “Fail” which are bound to the PLC and “Status” which is bound to an expression that is sets to 0,1 or2 based on Run and Fail.

What is the best way to dynamically set these colors based on “Status” in the repaint script? Also is there a way to set this globally? Perhaps in a table that the datasets could be bound to so one could change the color animation scheme for the entire project in a single location.

Sorry I know these a rookie questions but any insights would be great. Hopefully by the time I complete this conversion from InTouch my posts will be much more intelligent.

Regards,

Wes

Hey Wes,

There are a lot of ways you can do this. In cases where I have a lot of different color options, I pass in a string that contains the colors and parse them nto a list, and index off the list with the status values. But of you just have a few status values, some simple “if” logic will fo the job, i.e.:

if status==1:
    paintColor=drkgrad
elif status==2:
    paintColor=ltgrad
else:
    paintColor=Color(Color.WHITE)

rec=Rectangle2D.Double(0,0,100,200)
g.setColor(paintColor)
g.fill(rec)
g.setColor(Color.BLACK)
g.draw(rec)

As you mentioned, these color choices could be stored in a table, and that’s what I do as well. You could have a dynamic dataset property in your canvas container that grabs the project colors, and it will update with the current colors when you open the screen (I don’t use polling for configuration items like this).

Anyway, I use the canvas extensively, and will help you out with questions anytime.

Thank you for the help, it works great. :prayer:

just as a sanity check is there a cleaner way to code this:

my DataSet called “myColorIndex” is defined as follows:

"#NAMES" "Ind","drkRed","drkGreen","drkBlue","ltRed","ltGreen","ltBlue" "#TYPES" "I","I","I","I","I","I","I" "#ROWS","3" "0","127","127","127","215","215","215" "1","0","108","0","79","255","79" "2","213","0","0","255","155","155"

and I set the colors in the EventHandler like so:

colr = event.source.myColorIndex locStat = event.source.myStatus drkgrad = Color(colr.getValueAt(locStat,"drkRed"),colr.getValueAt(locStat,"drkGreen"),colr.getValueAt(locStat,"drkBlue")) ltgrad = Color(colr.getValueAt(locStat,"ltRed"),colr.getValueAt(locStat,"ltGreen"),colr.getValueAt(locStat,"ltBlue"))

Thanks again for your help. (Next I have to make it blink on unacknowledged alarm.)

Wes

For you or anyone else who is using the canvas, I threw together a window that shows how you can make the objects respond to operator input. I have a customer that wanted a visual way for the user to move products to a quarantine area without typing or fat-fingering anything.

I can’t show the actual screen, but this kind of gets you there. There are eight boxes, linked togther by lines. There is a “rubberband” mode that allows you to move the boxes around. I added some labels so you can see that it tracks the coodinates of each box. With a little imagination, you can easily see how anyone could use the mouse up/down events to virtually drop, say, pallets of product from one area to another, and if the real product showed up where it wasn’t supposed to, it would be flagged.
Canvas.vwin (12.9 KB)

@Step7 - Wow, that is sweet! Are you beta testing 7.3? I think you could do some amazing things with the new vector 2D components.

I won’t have a chance for a few weeks. I already do some pretty intense stuff with the canvas (my entire projects are based on being able to dynamically create active components through Java2D and bind them to ‘tags’), and I wanted to toss this out there in case someone needed some nifty drag and drop functionality.

@step7… simply wow.
:prayer:

Very nice. And actually, you are using “vector graphics” with this demo. The paintable canvas has has always used vector graphics, just totally hand-cranked. Furthermore, even in 7.3, what you’ve done is still probably the best way to do it.

Here’s another example that’s a little more advanced, but uses a few new techniques. I hacked it a bit so I wouldn’t have to upload modules too, but in the real world the drawing components would be created in individual modules. But, for this example, it works the same way.

Anyway, most of us are familiar with an overhead flex-track gantry that moves some kind of other device. This screen shows an overhead view, and it’s pretty easy to see how it could be animated in real life.

If you think of the gantry from the top view, you have the top track, the cables in the track, the bottom track, and whatever it’s moving. To draw it on the screen, you just draw everything in reverse order, keeping in mind how much of the top section of track is overlapping the bottom section (this makes more sense if you see the screen).

This example also uses panning and zooming, and also has a home button in case you drag it somewhere and lose it. There is also a slider that animates the track, and if you zoom in on the ensds, you can see how it works.

Again, the code is a hack that I through together from multiple projects, but basically it works like this:

  1. There is a function at the top that draws the gantry and carrier whenever the position or scaling changes.

  2. The gantry is drawn according to input parameters such as length, width, anchored position, etc. You can change theseparameters to see what happens.

  3. I use buffered images so I don’t have to constantly create the components if they aren’t changing. I also use bufferend images when I need to draw more than one of any component. For instance, even when I am creating the gantry image, I also create a little section of track as its own image, and paint that on the gantry. It’s extremely fast, the performance will be the same for a short gantry or long gantry.

  4. I use a global dictionary to store the images. Whenever I change the scaling or touch the slider, I just delete the dictionary and the images get redrawn. This way, the canvas can constantly be repainted without ever executing the drawing code if nothing is changing.

This isn’t meant to be the best way, or even a good way, to do something like this. I have done some things a little different on recent projects, but the concept remains the same. As for the code, it ain’t pretty, but I can explain it if you have questions. :slight_smile:
Gantry.vwin (19.8 KB)