We can flip the tree around to get a better understanding of exactly how the tree works:
Here we can get a better idea of why we can only move up and down through the tree structure, and how getting to a component can be very different depending on where you start. Let's say we want to go to the New Value Text Field so that we can grab its value.
|Start From||Path To New Value Text Field|
|Edit Table Container|
|Enter Data Button|
To move up or down within the hierarchy, there are two special commands we can use on component objects: parent and getComponent(). The parent property allows us to grab a reference to whatever is directly above the component in the hierarchy, which in most cases is the root container. We could then access any component on the root container by using getComponent("Component Name") and then placing the name of the component we want to access within the parenthesis.
# This pseudo code shows how to grab the parent of a component component.parent # This pseudo code shows how to grab a child of a component component.getComponent("Text Field")
Both parent and getComponent() can be used as many times as necessary to reach the desired component, drilling up or down through layers of containers or or grouped components. Once you have a component reference, you can then access any one of that component's attributes by using the name of the property, just like when accessing a property on the source component.
There is one exception to the pattern of using
Now that we have an understanding of how the component hierarchy works, we can apply that knowledge to accessing a component from anywhere within the project. While moving up and down within the hierarchy remains the same, accessing our initial component can differ depending on where we start our script from.
Event Handlers get a special event object that has special properties depending on the type of event. Regardless of the event, all event objects have a source property, which gives the component that fired the event. When accessing a component from an event handler, we can first use
event.source to get a component on the window to start at. From there, we can use parent or getComponent() as needed to get to the component we need to access.
# This would access the text property of a Text Field component. print event.source.parent.getComponent('Text Field').text
When accessing a component from an event on the window, there will be a different path to the component than normal. If you already have a window object, you can use the function getComponentForPath(). This allows you to enter in the path to the component as a string (similar to expression bindings), and will end up looking something like this:
system.gui.getParentWindow(event).getComponentForPath('Root Container.Text Field').text
You can also get the Root Container directly using the getRootContainer() function. This link of code works the same as the one above:
Extension Functions get a special self object which is actually a direct reference to the component that the extension function is on. This provides a direct reference point from which to access other components within the component hierarchy.
# This would access the text property of the component running the extension function script. print self.text # This would access the text property of the component named 'Text Field' if it is in the same container. print self.parent.getComponent('Text Field').text
Client Event Scripts are special because they don't start with a direct reference to anything on a particular window. So, we have to use another means of finding a starting point on the window. The system.gui.getWindow() function allows us to get a reference to a window which we can use to navigate to the root container with
.getRootContainer(), and then to any component on that window. However, this will only work if the window is currently opened. If the window is closed, it will throw an error, which can be handled with normal exception handling.
# Start the try block in case the window is not open. try: # Grab the window reference and assign it to the variable window. window = system.gui.getWindow("Other Window") # Use the window reference to get the text property off of a text field. print window.getRootContainer().getComponent("Text Field").text # Handle the exception by opening an informative error. except ValueError: system.gui.errorBox("The window is not open!", "Error")
Project Library are unique in that how they access components can vary depending on where the Script Module is being called from and what is being passed to it. If the script module is being called from an event handler or an extension function, it is possible to pass in the event or self objects and use them within the script module.
# This code would go in a project script. We are defining our function that takes an event object # and uses it to find the value of the text property on the text field in the same container. def func(event): print event.source.parent.getComponent('Text Field').text
# On the action performed of a button on our window, we could then use this to call our function. myTestScript.func(event)
However, this may not always be the case. In these instances, it is possible to instead use the same method that Client Event Scripts use and grab the window object instead.
Some component properties have more complex property values. For example, Font properties typically have a type of "Font".
In most cases these property types are simply using some built-in Java AWT types. These can be manipulated from scripting in Ignition by importing the appropriate library.
from java.awt import Font event.source.parent.getComponent('Text Field').font = Font('Dialog', Font.BOLD, 50)
See the AWT javadocs for more information.