The row selector component in Ignition 7.6.7 reports ScrollPaneUI as its UI property, so it is a Java Swing JScrollPane subclass. Most of the "undocumented" properties are inherited Swing and AWT bean properties, and Swing documentation applies to them directly. A small set is Ignition-specific: data, dataIn, dataOut, dataQuality, appContext, dynamicProps, filters, allDataNodeText and expandAllDataNode. Setting a selection from script means reaching the component inside the scroll pane's viewport and using its Swing selection API. Listeners are Java interfaces implemented with a Jython class.
Sorting the property list into Swing-inherited and Vision-specific
The listing is a flat dump of every readable bean property, each flagged bindable. Sort it by origin before searching for documentation.
| Properties in the listing | Origin | Where to read about them |
|---|---|---|
UI, UIClassID, columnHeader, columnHeaderView, border, autoscrolls
|
JScrollPane / JComponent
|
Java Swing API docs for javax.swing.JScrollPane
|
ancestorListeners, componentListeners, containerListeners, focusListeners
|
Registered-listener arrays from JComponent/Component/Container
|
Swing/AWT event model; read-only views of what is attached |
focusCycleRoot, focusTraversalKeys, focusTraversalPolicy, focusOwner, focusTraversable
|
AWT focus subsystem | AWT focus documentation |
background, backgroundSet, cursor, cursorSet, bounds, alignmentX, alignmentY, doubleBuffered, debugGraphicsOptions, dropTarget, componentPopupMenu
|
Component/JComponent
|
Swing API docs |
data (RowFilteredDataSet), dataIn/dataOut (Dataset), dataQuality (int), filters (List), appContext (VisionClientContext), dynamicProps (TreeMap), allDataNodeText (String), expandAllDataNode (boolean) |
Ignition Vision | Inspect in the Script Console; these have no Swing equivalent |
The listing ends mid-way through the focus properties, so the properties that matter most for selection may sit past the truncation point. Enumerate them live with dir() as shown in the procedure below instead of reading a pasted list.
Why the properties look undocumented
Vision components are Swing objects, and Jython exposes any Java getX()/setX() pair as a property x. Ignition's component introspection lists every such pair, whether or not Inductive Automation wrote a manual entry for it. The result is dozens of entries where only a handful carry Ignition semantics.
Three mechanisms explain most of the confusion:
-
Listener properties are arrays, not hooks.
ancestorListenershas typeAncestorListener[]. It reports what is already registered. Assigning to it does not register a handler. Registration happens throughaddXListener()methods, which do not appear as properties. -
The scroll pane is a container. The visible rows are drawn by a child component held in the scroll pane's viewport.
columnHeader(JViewport) andcolumnHeaderView(Component) confirm a header viewport exists. The selection state lives on the child, not on theJScrollPane. -
Data is a wrapped dataset.
datais aRowFilteredDataSet, so the dataset the user sees can be a filtered subset ofdataIn.filters(List) holds the active filter definitions. Row indices in the displayed view and in the underlying dataset can differ when filters are active.
There is no dropdown-style selectedValue in the visible portion of the listing. Confirm absence with hasattr(comp, 'selectedValue') before designing around one.
Discovering the live API of the component in Ignition 7.6.7
- Place a button on the same window. In its
actionPerformedhandler, get the component:comp = event.source.parent.getComponent('RowSelector'). Replace the name with the component's actual name. - Print the wrapper class and data types:
print comp.__class__,print comp.data.__class__,print comp.dataIn.rowCount. - Print the child that draws the rows:
view = comp.viewport.view, thenprint view.__class__. Jython mapscomp.viewport.viewtogetViewport().getView(). - List every property and method on that child:
print dir(view). AsetRowSelectionIntervalentry indicates aJTable. AsetSelectionRowentry indicates aJTree. - Look up the class name printed in step 3 in the Java Swing API docs for the Java runtime bundled with the Ignition client. Read the Java version with
from java.lang import System; print System.getProperty('java.version'), because method availability tracks the runtime. - Print
comp.filtersand comparecomp.data.rowCountwithcomp.dataIn.rowCount. A difference means the view is filtered.
Setting the selection from a script
Branch on the class found in step 4 above.
| Child class | Select a row | Read the selection |
|---|---|---|
JTable |
view.setRowSelectionInterval(r, r) |
view.getSelectedRow() |
JTree |
view.setSelectionRow(r) |
view.getSelectionRows() |
These are standard Swing methods; the index r is a view index. When filters is non-empty, translate a dataset row to a view row by searching the displayed data for the key value rather than reusing the dataIn row number. Run the selection call on the Swing event thread. Ignition's system.util.invokeLater serves that purpose when the call originates from a non-UI thread such as a gateway message or timer script.
To mirror a dropdown's selectedValue behavior, keep a custom property on the window, write it from a selection listener, and drive the selection from a change script on that property.
Implementing listeners in Jython
Swing listeners are Java interfaces. Jython implements them with a Python class that extends the interface or its adapter class, then registers an instance through the matching add method.
from java.awt.event import MouseAdapter
class RowClick(MouseAdapter):
def mouseClicked(self, e):
print 'clicked at', e.getPoint()
view = comp.viewport.view
view.addMouseListener(RowClick())
For selection changes on a JTable, register on the selection model:
from javax.swing.event import ListSelectionListener
class SelWatch(ListSelectionListener):
def valueChanged(self, e):
if not e.getValueIsAdjusting():
print 'selected row', view.getSelectedRow()
view.getSelectionModel().addListSelectionListener(SelWatch())
For a JTree, use javax.swing.event.TreeSelectionListener and view.addTreeSelectionListener(...). Standard Vision event handlers configured in the Designer are the first choice for events Ignition already exposes. Reserve raw listeners for events it does not.
Verification checks with expected readings
- Run
print comp.UI. Expected: aScrollPaneUIinstance, matching the listedUItype. - Run
print comp.viewport.view.__class__. Expected: a Swing selection-capable class (table or tree). AJPanelor other container means the rows are one level deeper; repeat with.components. - Call the selection method from the table above with a known row. Expected: the row highlights, and the read method returns the same index you passed.
- Add the listener class, then read
comp.viewport.view.mouseListenersor the selection model's listener array. Expected: your listener instance appears in the array. - Click a row with the mouse. Expected: the listener prints once per completed selection (
getValueIsAdjusting()false), not repeatedly during a drag. - With a filter active, select the same key value by view index and by dataset index. Expected: the two indices differ, and only the view index highlights the intended row.
Pitfalls that recur with scripted Swing selection
-
Assigning to a listener array property.
ancestorListeners,focusListenersand the others are read-only reports. UseaddXListener(). -
Listeners lost on window reopen. Closing and reopening a window builds new component instances. A listener attached to the previous instance never fires again. Register from the window's
internalFrameActivatedevent or from a componentpropertyChangescript so registration repeats each time the window opens. -
Stacked duplicates. Registering from an event that fires repeatedly adds a new listener each time. Remove the previous one with the matching
removeXListener(), or guard with a check against the listener array. -
Selecting before data arrives. Calling a selection method while
dataInis empty or a binding is still loading selects nothing or throws an index error. Checkcomp.data.rowCount > 0first. -
Trusting a pasted property list. Runtime
dir()output reflects the installed Ignition build and the actual child class; documentation excerpts do not.
FAQ
Why does the Ignition row selector expose so many undocumented properties?
The component extends Swing's JScrollPane, and Ignition lists every Java bean property it inherits, such as focusTraversalKeys and componentListeners. Only data, dataIn, dataOut, dataQuality, filters, appContext and dynamicProps among the listed items are Vision-specific.
Why does setting a selectedValue-style property fail on the row selector?
A dropdown exposes selectedValue as its own property, but no such property appears in the row selector's listing. Select through the viewport child instead, for example comp.viewport.view.setRowSelectionInterval(r, r) if the child is a JTable.
Why does my script listener stop firing after the window is reopened?
Reopening a window creates new component instances, and the listener you added belongs to the old one. Re-register the listener each time the window activates, and call removeXListener() first to avoid duplicates.
Why does Java Swing documentation apply to Ignition Vision components?
Vision components are Swing objects, and Jython maps getX()/setX() pairs to properties. Confirm the class with print comp.viewport.view.__class__, then read that class's Javadoc for the selection and listener methods.