Is there any way to dynamically create objects at run-time? I’m thinking of something like a factory overview page with custom icons pasted at locations read from a database.
Al
Is there any way to dynamically create objects at run-time? I’m thinking of something like a factory overview page with custom icons pasted at locations read from a database.
Al
Sorry, this is currently an unsupported feature. You cannot add components dynamically in the runtime.
You can, however, use the Paintable Canvas component to draw shapes or images at different points on the screen. For this to work, the component needs to be the same size as the root container and anchored to all 4 sides. Here is an example repaint script that paints circles at random locations on the screen:[code]from java.awt import Color
from java.awt.geom import Ellipse2D
from java.util import Random
g = event.graphics
circleHeight = 16.0
circleWidth = 16.0
circle = Ellipse2D.Float(0,0,circleWidth,circleHeight)
random = Random()
for i in range(10):
#### Move to a x,y location and paint circle
x = random.nextInt(500)
y = random.nextInt(500)
g.translate(x,y)
g.setColor(Color.GREEN)
g.fill(circle)
g.setColor(Color.GREEN.darker())
g.draw(circle)
g.translate(-x,-y) # Make sure you move back to starting point[/code]Here is an example repaint script that paints images at random locations on the screen:[code]from java.awt import Color
from javax.swing import ImageIcon
from java.util import Random
from java.net import URL
gatewayAddress = fpmi.system.getGatewayAddress()
g = event.graphics
image = ImageIcon(URL(“http://%s/gateway/images/Builtin/icons/16/lightbulb_on.png” % (gatewayAddress)))
random = Random()
for i in range(10):
#### Move to a x,y location and paint circle
x = random.nextInt(500)
y = random.nextInt(500)
g.drawImage(image.getImage(), x, y, None)[/code] Hope this helps.
Hi Travis,
I tried your examples and they worked well, although setting the paintable canvas to the front of the z-order so it appeared as an overlay on top of other controls could result in rather unpredictable results. For example, if you place a Text Area control on the screen, scrolling the text area at runtime resulted in lots of circles/images being drawing at random over it. I would imagine this has something to do with the control repaint conflicting with the paintable canvas repaint. This problem seemed to disappear if I changed the paintable canvas code to put objects into predefined positions.
The problem with this approach is that you do not the advantages of treating everything like objects with their own events. If I continue with this approach I would have to manually draw everything, then manually deal with events like detecting when a user clicks on an icon etc. (As an aside, I was looking for some way to detect where the user pressed the mouse and came across the undocumented fpmi.gui.convertPointToScreen function in one of Carl’s downloads in this post.) When doing this I found that the paintable canvas ‘absorbed’ all of the mouse clicks, meaning other controls underneath it did not respond. Also, I was getting the absolute screen position, not the position within the paintable canvas - is the latter possible?
Whilst the paintable canvas is undoubtedly very powerful, it does seem something of a backward step in this particular application, compared to instantiating and manipulating pre-defined objects.
I was thinking a better approach may be to have a ‘stock’ of pre-defined objects in the Window with their Visible property set to false - if they are required, they are put in the correct position at the correct size and made visible.
Al
I’ve managed to get the position of the mouse click within the paintable canvas by using event.getX() and event.getY() within the paintable canvas mousePressed event. I found these methods by looking at Java documentation, but I don’t know enough to know whether this is the correct approach.
Al
I’m not technical enough in the Java2D arena - Carl, Travis, Kevin, or Colby should be able to help out. I think you’re really stretching the functionality of the Paintable Canvas component, which is a good thing. What you really need is Native 2D drawing (coming) and the ability to instantiate multiple components (maybe). Lots of good development going on in that direction - I don’t think you’ll be disappointed.
Al, I’ve done something with the paintable canvas that does pretty much what you describe. I can post it later (it’s on another PC), but this is the approach:
Like I said, I’ll post what I’ve got later. I’d like to have someone else come up with more ideas for this.
Al, I’ve attached a few things if you’re interested. It’s mostly stuff I am playing around with, and is far from being a true “dynamic object library”, but could be made into something pretty useful for a screen that has a lot of objects that change state a lot. By adding more drawing scripts, each iteration could be a different object if the object type was passed in. I documented the code fairly well, but it’s pretty straightforward anyway. I’m not an expert, and I’m sure there are better ways to do it, but it works for now.
Just import the two scripts and window, and create a table based on the column snapshot I attached. Or, change the bind properties of the root container “modList dataset” to use tags instead of a table (I didn’t have a plc for my testing). The binding is done directly on the dataset with polling off so it’s initialized on startup, but then updated on the canvas “mouse pressed” event after that. The slider can draw up to 500 pumps, so you will need at least 500 records or tag sets, or just decrease the slider max value. To make the canvas repaint, just increment the canvas “repaint” dynamic property.
I’m just using the IA Pump drawing with a few things stripped out (the dynamic stuff). After it’s drawn to an image, I paint the title and a feedback bar to indicate speed. The rotate button is there to test how well the screen will paint, as is the zoom in and zoom out buttons. If you click on a pump, it will invert 180 degrees, which is how I am testing events.
I’m working on more stuff to make it more workable, but it’s a start.
Pump12.zip (39.1 KB)
This sounds like the most pragmatic approach to me.
It is in our documentation also, here : inductiveautomation.com/prod … .htm#mouse
Step 7,
Thanks for posting your code . Unfortunately I get an error if I try to increase the number of pumps - an ‘index out of range’ error at line 101 in drawPump. Maybe something to do with the values in the TestModules table. I can display one pump however and see it respond to a mouse click.
I can appreciate the raw power this kind of thing gives, but my natural laziness wants an easier way!
Al
Carl,
Just call me pragmaticAl from now on
I see the entry in the manual giving mouse event x and y coords (cunningly accessed using event.x and event.y). You’re going to have to lower your standard of service and force us to read the manual
Ah ha! Is that how we get you guys to read it? Ok, we’ll have to work on that…