Iterate Through Components In Container (Vision)

(v8.1.35)

I have a need to iterate through multiple components within a container.

Each component is an easychart and I want to be able to go through each one and perform the same script. Rather than manually call the script for each chart and having to manually add/remove calls as charts are added/removed I would like to just loop through all of the components in the container.

Based on this post I thought I would be able to use the .component object to iterate through the component list.

#get the container that holds all of the charts
chartsContainer = system.gui.getParentWindow(event).getComponentForPath('Root Container.Charts')

#for each chart in the container, update the path to the tagPen as needed
for easyChart in chartsContainer.component:
	Trending.historyPathConvert_MasterToEdge(easyChart)

I get the following error.

Traceback (most recent call last):
  File "<event:visionWindowOpened>", line 5, in <module>
AttributeError: 'com.inductiveautomation.factorypmi.application.com' object has no attribute 'component'

	at org.python.core.Py.AttributeError(Py.java:176)
	at org.python.core.PyObject.noAttributeError(PyObject.java:965)
	at com.inductiveautomation.factorypmi.application.script.PyComponentWrapper.noAttributeError(PyComponentWrapper.java:563)
	at org.python.core.PyObject.__getattr__(PyObject.java:959)
	at org.python.pycode._pyx31.f$0(<event:visionWindowOpened>:5)
	at org.python.pycode._pyx31.call_function(<event:visionWindowOpened>)
	at org.python.core.PyTableCode.call(PyTableCode.java:173)
	at org.python.core.PyCode.call(PyCode.java:18)
	at org.python.core.Py.runCode(Py.java:1703)
	at com.inductiveautomation.ignition.common.script.ScriptManager.runCode(ScriptManager.java:804)
	at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:207)
	at com.inductiveautomation.factorypmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:300)
	at com.inductiveautomation.factorypmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:57)
	at jdk.proxy2/jdk.proxy2.$Proxy46.visionWindowOpened(Unknown Source)
	at com.inductiveautomation.factorypmi.application.FPMIWindow.fireVisionWindowOpened(FPMIWindow.java:719)
	at com.inductiveautomation.factorypmi.application.VisionDesktop$RuntimeWindowOpener.openWindow(VisionDesktop.java:549)
	at com.inductiveautomation.factorypmi.application.VisionDesktop.openWindow(VisionDesktop.java:192)
	at com.inductiveautomation.factorypmi.application.VisionDesktop.openWindow(VisionDesktop.java:184)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.lambda$swapWindow$0(NavUtilities.java:197)
	at com.inductiveautomation.factorypmi.application.script.builtin.WindowUtilities.doGUIAction(WindowUtilities.java:853)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.swapWindow(NavUtilities.java:196)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.swapTo(NavUtilities.java:105)
	at com.inductiveautomation.factorypmi.application.script.builtin.NavUtilities.swapTo(NavUtilities.java:92)
	at com.inductiveautomation.factorypmi.application.components.tabstrip.PMITabStrip.setSelectedTab(PMITabStrip.java:482)
	at com.inductiveautomation.factorypmi.application.components.tabstrip.TabHolderPanel.mousePressed(TabHolderPanel.java:243)
	at java.desktop/java.awt.AWTEventMulticaster.mousePressed(Unknown Source)
	at java.desktop/java.awt.Component.processMouseEvent(Unknown Source)
	at java.desktop/javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.Component.processEvent(Unknown Source)
	at java.desktop/java.awt.Container.processEvent(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.desktop/java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.desktop/java.awt.Component.dispatchEvent(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(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.desktop/java.awt.EventQueue$5.run(Unknown Source)
	at java.base/java.security.AccessController.doPrivileged(Unknown Source)
	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)

Ignition v8.1.35 (b2023120517)
Java: Azul Systems, Inc. 17.0.8

I used the property browser to make sure I got the correct path to the Charts container, and I also confirmed that it is a container and not a group.

It should be:

chartsContainer.components

or this will also work:

chartsContainer.getComponents()

Edit: added bean property option per the feedback below

1 Like

better would be:

chartsContainer.components
4 Likes

Important caveats to note:
Your current approach doesn't check if the component is actually a chart, and your current approach doesn't do a "deep" walk, in case there's any nested container that itself contains a chart.

1 Like

You can modify this function to make it work for you - Fetching a component's data from window and transfer that value to Translation Manager - #2 by bkarabinchak.psi

This does a recursive call for inner containers.

1 Like

That's what I had that caused the error

*edit: I see I was missing the "s". Should be components not component

I don't have a need for that here, but good to know.

Thanks

No you had chartsContainer.component, not chartsContainer.components notice the s

1 Like

Why is it better?

I'll let @pturmel tell you. :wink:

Basically, anytime in ignition you see a method with signatures get*(), set*(), and is*() you should prefer to use the jython property instead. So .getComponents() becomes .components.

I don't believe that this happens for anything other than default getters and setters, and the standard boolean gettter .isXyz()

2 Likes