Why can't custom properties and methods be accessed from a component that is obtained using SwingUtilities.getAncestorOfClass?

When I need to get a certain type of parent from a generic component such as a template, and I can't predict how deeply the component will be nested from one instance to the next, I simply obtain the parent with swing utilities because it's simpler and cleaner than a recursive script. However, every now and then, I find myself retrieving a parent component with a custom method or property that I need to call or manipulate, and if I use swing utilities, I find that the custom attributes are lost.

Obviously, this is not a show stopper because this scenario doesn't occur very often, and when it does, I can simply use a recursive function instead, but I'm curious why this is, and if there is a simple work around.

Custom properties are added to the java standard jython conversion by IA's PyComponentWrapper. For a complete discussion, read this entire topic:

TL/DR: Install my Simulation Aids module to magically fix this, everywhere in Ignition. There is no other solution until IA eventually does this first party.

1 Like

Thanks for the hint. Wrapping the swing utility call in the PyComponentWrapper returns the object with the custom properties accessible.

Just for completeness and clarity; the recursive approach always works for returning a component with its custom properties.

Recursive example to get the parent container of a component:

from com.inductiveautomation.factorypmi.application.components import BasicContainer
def getParentContainer(component):
	if isinstance(component.parent, BasicContainer):
		return component.parent
	else:
		parentContainer = getParentContainer(component.parent)
		if parentContainer is not None:
			return parentContainer
parentContainer = getParentContainer(event.source)

The getAncestorOfClass approach returns the expected component and takes far fewer lines of code, but all custom properties are lost:

Basic SwingUtilities Example:

from com.inductiveautomation.factorypmi.application.components import BasicContainer
from javax.swing import SwingUtilities
parentContainer = SwingUtilities.getAncestorOfClass(BasicContainer, event.source)

By simply wrapping the swing utility call in a pyComponentWrapper call, the component is returned with the custom properties just like the recursive approach.

pyComponentWrapper with SwingUtilities example:

from com.inductiveautomation.factorypmi.application.components import BasicContainer
from com.inductiveautomation.factorypmi.application.script import PyComponentWrapper
from javax.swing import SwingUtilities
parentContainer = PyComponentWrapper(SwingUtilities.getAncestorOfClass(BasicContainer, event.source))

It's only one more line of code, and it's still cleaner looking than building a recursive function.

2 Likes

Neat. Hadn't thought of that.

Not as neat as never worrying about it again after installing Simulation Aids.

2 Likes