System.gui.transform on template

Is it possible to use system.gui.transform inside of a template? I tried, but it throws error (component is not in a standard container - line 9 is when I call system.gui.transform:

Traceback (most recent call last):
  File "<event:propertyChange>", line 9, in <module>
	at com.inductiveautomation.factorypmi.application.script.builtin.WindowUtilities.transform(WindowUtilities.java:380)
	at jdk.internal.reflect.GeneratedMethodAccessor743.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
java.lang.RuntimeException: java.lang.RuntimeException: Component is not in a standard container.

	at org.python.core.Py.JavaError(Py.java:552)
	at org.python.core.Py.JavaError(Py.java:543)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)
	at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.__call__(ScriptManager.java:539)
	at org.python.core.PyObject.__call__(PyObject.java:413)
	at org.python.pycode._pyx354.f$0(<event:propertyChange>:9)
	at org.python.pycode._pyx354.call_function(<event:propertyChange>)
	at org.python.core.PyTableCode.call(PyTableCode.java:171)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1614)
	at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:799)
	at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:206)
	at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter$ActionRunner.run(ActionAdapter.java:312)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.lang.RuntimeException: Component is not in a standard container.
	at com.inductiveautomation.factorypmi.application.script.builtin.WindowUtilities.transform(WindowUtilities.java:380)
	at jdk.internal.reflect.GeneratedMethodAccessor743.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188)
	... 23 more

Ignition v8.1.5 (b2021042810)
Java: Azul Systems, Inc. 11.0.10

Having same issue.

Not sure if the transform works on the template itself within a repeater.

You have to get the template holder, and perform your transform on that. Scripting, within the template, I accomplish this with swing utilities, getAncestorOfClass.

I saw your post about Power table scroll, could you guide little more towards how would you do it on Graph within a template ?

I'm sure I can help, but refresh my memory?

...and if you haven't already, since this doesn't seem related to the current topic, make a new topic for this question. It will make it easier for others to find.

Thanks

Here is proper example of getting the template holder and performing a transform on the template:

from javax.swing import SwingUtilities
from com.inductiveautomation.factorypmi.application.components.template import TemplateHolder
templateHolder = SwingUtilities.getAncestorOfClass(TemplateHolder, event.source)
if templateHolder is not None:
	system.gui.transform(templateHolder, newWidth=100, newHeight=100)

This will work from the event handler of any component in the template or the template itself. However, it's worth noting that the transform will only take place if the template has been placed in a window. If this script is fired from the template editor in the designer, nothing will happen because the template holder will not exist.

It's also possible to get the template holder by simply adding .parent however many times it takes to get one level above the template itself, but I would still run an if isinstance to prevent an unexpected behavior or unwanted exception if the script somehow gets fired from the template editor.

1 Like

Thanks for the reply @justinedwards.jle ,
Tried to put this on Template Script but no luck.

Can't get the templateHolder.

• I don't see anywhere in your picture where you are calling the updatePlotSize() function
• I don't recommend the use of try/except here. You already have a if statement that will tell you if you are running this from the designer outside of a window. If you need it printed, add an elif.

Which propertyChange event should call this?

Also, I have to make sure:
This template has been dragged and dropped into a window correct? ...and the window is where the script is being called from? Unless the template is nested inside a Vision window, there won't be a template holder to transform.

1 Like
  1. updatePlotSize() is grayed out just under the function. I was trying to different things and one of them was to put that as InvokeLater.
  2. Try and Except was also part of the testing where I was trying to see if the Width Property of the template itself was any useful.

So the script is being called on update property event which is basically an initialization trigger for the template. The Template is inside the template repeater.

Script is here :

This is where the template is used :

I see; this is a different scenario. The template repeater is going to arrange the templates based on the selected layout. Are you wanting to transform the repeater itself? The repeater should be obtainable from the template in the same way. I don't know what the full import path is off the top of my head, but it should be easy to find.

The Problem is, If I transform the repeater, it does not create the scroll bar automatically.
The idea is to enlarge the chart inside a template big enough (normally done through calculation where width = number of rows in chart dataset * Pixel Rate , for example = 10).

Consider using a template canvas instead of a template repeater. You still won't be able to use transform, but the canvas's dataset allows you to directly set the width, height, and position of each individual template. Furthermore, if there is overflow, a scrollbar will automatically appear.

1 Like