Passing parameters from a table row to a chart window

I read the color change posting and I understand most of the concept. But what I need to do is click on a row in a History table, have a chart window open and draw a graph according to the data in the table row, the start and end dates in date boxes (not in the table, but dropdowns themselves):

These date dropdowns are in the window with the table:

Start Date: 9/1/06 12:00:00 AM (Separate from the table)
Stop Date: 9/3/06 18:00:00 AM (Separate from the table)

This is the History Table Row Data:

Time Stamp Item Cleaned Operator Name
9/1/06 13:45:00 PM 13 M. Smith
9/2/06 5:30 AM 5 B. Jones
9/3/06 17:22:00 PM 36 M. Cutty

Currently, I can call up the chart screen, set the desired parameters and display the desired graph. On another History screen, I can call up a list of all the items run for any period of time. However, I would like to click row 2 above in the History table and immediately show the chart for B. Jones activity on 9/2/06, without having to select the specific dates and Item Cleaned ID again for the desired graph, and without displaying the other activity dates and data. How close can I get?

Glen Johnson

Glen,

First of all, the recent post about color changing in tables has very little to do with what you’re asking, so don’t get confused by that post.

It sounds to me like what you’re trying to do is to pull data out of the table based on the selected row, and with that data, open a Chart window and have that data passed into the chart window, so that the chart window opens up showing the correct data.

This isn’t very difficult. First, you need to isolate what data the chart window needs. It sounds like the chart needs a day and an Item ID.

The first step is to make a chart window that is set up to chart data based on parameters that the window has recieved. To do this, add the parameters needed as dynamic properties on the root container of the chart window. Get the chart window working before moving onto the next step. You can test this window’s functionality by manually changing the values of the parameters in the Designer.

The next step is to write a script on the window with the table that gathers the necessary parameters and opens the Chart window with these parameters. Practice getting this script correct by first putting it in a Button next to the table, and then we can move the script into the Table’s mouse clicked event.

Here is a skeleton example of what this script might look like:

[code]table = event.source.parent.getComponent(“Table”)

selectedRow = table.selectedRow

if selectedRow == -1:
fpmi.gui.errorBox(“Please select a row”)
else:
# Gather the necessary parameters
t_stamp = table.data.getValueAt(selectedRow, “Time Stamp”)
itemId = table.data.getValueAt(selectedRow, “Item Cleaned”)

# Open the chart window, passing in the parameters.
# The chart window must have dynamic properties on its
# root container that correspond to these names
fpmi.gui.openWindow("ChartWindow", {"TimeStamp": t_stamp, "ItemID":itemId})

[/code]

Hope this helps, let me know if you have questions or would like more help

Related to this, we have a portion of our plant where we are using factorysql for data acquisition direct from the plc, and for these tanks I have a lot of very detailed information.

There are many other tanks in older parts of the plant where I have less information.

An additional complication is that the two sets of data are stored in different dbs on different servers.

I would like to set the datasources and queries dynamically based on some parameters I pass in to the new window. Is this possible? TIA D. Lewis

David,

Queries - Yes.
Datasources - Unfortunately, not at this time. This is a pending feature request.

First of all - to make queries dynamic based on pased-in parameters passed into a window, all you do is have your SQL queries bound to String-typed dynamic properties in the root container, and then you can pass values in for these properties. (using the ubiquitous but small 'link button' in the upper-righthand side of the SQL Query binding window)

Datasources cannot be made dynamic at this time. Some thoughts on your situation: If some of the tanks have lots of information, and some have minimal information, the two types of tanks probably should just have two different popup windows, because the information shown will be different. With two different popup windows, the datasources don't need to be dynamic in the first place.

If you are dead-set on having a value that pulls from two different datasources dynamically, the design would go something like this:

Have a custom property for your value that you want (maybe the value is a DataSet that pulls all information for a tank)

Have two other custom properties that pull this value using a SQL binding from the two different datasources (lets call these properties Value_DS1 and Value_DS2

Have some sort of property that defines which dataset to use. Lets call it WhichDatasource that will be a string.

Lets say all 4 of these properties are on the root container. You'd then bind your initial value (the value that the components on the screen actually use) to an expression like:

if({Root Container.WhichDatasource} = "DS1", {Root Container.Value_DS1}, {Root Container.Value_DS2})

I hope this makes sense. Let me know how we can be of further assistance,

I agree with Carl that having two separate popup windows probably makes the most sense. That way your queries are simple and you don’t have to deal with complex binding arrangement .

I wanted to point out that this is seamless to the end user. As far as they can tell, they’re selecting the table row, and opening another window. Your Jython code can distinguish the conditions for each window with a simple if statement, and open the correct popup window accordingly.

Hi All:

Beginning with the most simple task of putting a button on a window that when clicked will open another window with a value from the selected row as an opening argument, I tried doing this but when I try to attach the following code snippet to the mouseClicked event of the button:

table = event.source.parent.getComponent(“tblTTrack”)

selectedRow = table.selectedRow

if selectedRow == -1:
fpmi.gui.errorBox(“Please select a row”)
else:

Gather the necessary parameters

FERMID = table.data.getValueAt(selectedRow, “FERMID”)

Open the chart window, passing in the parameters.

The chart window must have dynamic properties on its

root container that correspond to these names

fpmi.gui.openWindow("wnChartSingle, {“FERMID”: FERMID})

I get an error saying
Unable to register mouseClicked event
Parse Error:
Traceback (innermost last):
(no code object) at line 0
SyntaxError:(‘invalid syntax’,(",15,42,'fpmi.gui.openwindow("wnChartSingle,{“FERMID”:FERMID}) '))

Any thoughts? TIA D. Lewis

David,

You’re missing a closing quote on the window name: “wnChartSingle”

The full code would be:

[code]table = event.source.parent.getComponent(“tblTTrack”)

selectedRow = table.selectedRow

if selectedRow == -1:
fpmi.gui.errorBox(“Please select a row”)
else:
# Gather the necessary parameters

FERMID = table.data.getValueAt(selectedRow, "FERMID") 

# Open the chart window, passing in the parameters. 
# The chart window must have dynamic properties on its 
# root container that correspond to these names 
fpmi.gui.openWindow("wnChartSingle", {"FERMID": FERMID})

[/code]

Hope this helps,

Ah. Of course. Thanks.

Hi Carl:

I don’t suppose the app.nav module can handle the parameters?

I tried it and it broke, so I am assuming I need to modify it? At the moment have only one window to open, passing it one parameter, but I can easily forsee more windows in the future, some with parameters (one or more) some without.

Should I give up on trying a generic app.nav approach? TIA D. Lewis

David,

(edit - for those not familiar with it, app.nav is a FactoryPMI goodie library module, available at http://www.inductiveautomation.com/products/factorypmi/goodies/)

The app.nav module does handle parameters, but it only implements a swapTo() function. It looked like you were doing an openWindow(). The app.nav module’s primary purpose is to keep track of your current ‘main screen’, so that swaps can be performed from menu items, docked windows, etc. A call to fpmi.gui.openWindow is usually opening a popup window, and is therefore not affecting the main screen, hence the lack of an openWindow in the app.nav goodie.

Does this make sense? Let me know if I’m correct in assuming that you’re doing an openWindow and not a swap. If the app.nav module is breaking on a swap, then something is wrong with the way you are calling app.nav.swapTo.

(FYI - this conversation has inspired me to update the app.nav module and include some more functionality. Stay tuned. And, remember that you can look (and edit) at the app.nav module directly if you are ever confused about what it is doing)

Hope this helps,

I see. It is mostly my problem: I wasn’t really aware of what I was doing (Openwindow versus swapwindow, etc.). I read up on them in the documentation and try again. Thanks. David

Ok. Here is some background so you don’t have to go digging through the docs if you don’t want to:

There are two ways to open windows in FactoryPMI, calling fpmi.gui.openWindow() and calling fpmi.gui.swapWindow().

openWindow() takes the name of the window to open, and optionally, a dictionary of parameters to pass into the window.

swapWindow() has two variants. One takes an event object, the name of a window to swap to, and optionally, a dictionary of parameters. The other variant takes a ‘swap from’ window name. Before I explain the difference, here is what a swap is:
[ul]Opens the ‘swap to’ window.
Makes that window the same size and maximization state as the ‘swap from’ window.
Closes the ‘swap from’ window.[/ul]
The effect for the end user is that one window has ‘turned into’ another. This is used extensively in FactoryPMI to create the effect that users are used to from other HMI packages - that there is one ‘main screen’, that changes based on things that you click.

The first variant of fpmi.gui.swapWindow takes an event object (all action scripts have an ‘event object’ in their namespace that describes the event that occured). It uses this event object to determine the swapWindow (all events take place in a window, so you can find the window that the event occured in.) The second variant of fpmi.gui.swapWindow takes a ‘swap from’ name. This is so that you can perform swaps of the main window from a docked navigation window or from a menu item in the dynamic menu bar.

This brings us to the app.nav goodie library. This library funnels all calls to fpmi.gui.swapWindow through the function app.nav.swapTo (which only takes a ‘swap to’ name, and the parameter dictionary), and then uses Jython to keep track of what the current ‘main screen’ is. This enables you to swap windows from docked navigation window or a menu item, because without this, you wouldn’t know what the current ‘main window’ was.

Hope this clears things up,

Hi Carl,

So, what I understand from your post is that for my purposes swapWindow is what I want (replace one window with another), and that the app.nav goodie can take 0 or any number of parameters – it simply depends upon how I want to invoke it in each instance. Correct?

Based on that, I imported the module to my project, named it nav, and attached the code to a button. The button is intended to collect an integer (in a hidden column) from a highlighted row in a table, then open a graph window passing in that integer value. Below is the code for that, essentially the app.nav code:

/code
table = event.source.parent.getComponent(“tblTTrack”)
selectedRow = table.selectedRow
if selectedRow == -1:
fpmi.gui.errorBox(“Please select a row”)
else:

Gather the necessary parameters

FERMID = table.data.getValueAt(selectedRow, “FERMID”)

Open the chart window, passing in the parameters.

The chart window must have dynamic properties on its

root container that correspond to these names

app.nav.swapTo(“wnChartSingle”, {“FERMID”: FERMID})
#fpmi.gui.openWindow(“wnChartSingle”, {“FERMID”: FERMID})
/code

This produced the following error:

Note: If I uncomment the swapWindow line and instead use the openWindow line, it all works fine.

TIA D. Lewis

Traceback (innermost last):
File “event:mouseClicked”, line 16, in ?
AttributeError: instance of ‘com.calmetrics.factoryhmi.application.script.PyHMIPackage’ has no attribute ‘nav’

at org.python.core.Py.AttributeError(Py.java)
at org.python.core.PyObject.__getattr__(PyObject.java)
at org.python.pycode._pyx4.f$0(<event:mouseClicked>:16)
at org.python.pycode._pyx4.call_function(<event:mouseClicked>)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyCode.call(PyCode.java)
at org.python.core.Py.runCode(Py.java)
at com.calmetrics.factoryhmi.application.script.ScriptManager.runCode(ScriptManager.java:156)
at com.calmetrics.factoryhmi.application.binding.action.ActionAdapter.runActions(ActionAdapter.java:137)
at com.calmetrics.factoryhmi.application.binding.action.ActionAdapter.invoke(ActionAdapter.java:277)
at com.calmetrics.factoryhmi.application.binding.action.RelayInvocationHandler.invoke(RelayInvocationHandler.java:54)
at $Proxy0.mouseClicked(Unknown Source)
at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

David,

It sounds like you made a package called “nav”, and then imported the nav module into that package.

To import the app.nav goodie, just import the module (the file named nav.py) directly into the ‘app’ package.

Let me know if this wasn’ the case,

Carl:

As far as I can see, that is what I did. I’ll send a screenshot of the import screen separately. David

What version of FactoryPMI are you using? Previous to version 1.7.0, you had to save your project before changes to the library scripts took effect.