Another List Question

I’m using your List component in multiple interval mode to create a multi-select drop-down list. I assume that multi-select isn’t possible with your drop-down list component, right? Anyway, that’s why I went this route.

I’ve attached a sample window, and there is a minor issue: I would like to calculate the size of the list box dynamically as the list grows. But, I don’t see any property that gives me the row height. So, I looked at the Java API and found a List component that I think is the same as what you are using, and there are getMinimumSize() and getMinimumSize(int) methods. The first one will return a value, but the second one gives me a fault. And, the value that the first one returns doesn’t seem to be useful, since there is no way it can determine a minimum size if it doesn’t know how many rows there will be, right? Or maybe I am just misunderstanding what getMinimumSize will do.

So, I emperically determined what a row height will be, but I think there must be a better way. If not, that’s ok. It works well the way it is. I just want to avoid making the box too big, because if the user clicks on the dead space beneath the items, the last item is selected.
ListTest.fwin (5.11 KB)

Sorry, those sizes you're looking at don't have anything to do with the row height anyhow - they're for the entire list.

I'm not sure that you want to do this at all - you're really subverting how the list works with regards to scrolling.

Is this a problem?

I will have a max of about 30 items in my lists, so I wanted to avoid scrolling just to make the wizard work a little quicker. It’s no big deal though. I just thought there might be a row height property somwhere.

As for the white space, it also isn’t a big problem other than it seems to act different from all other white space in containers. For instance, if I have a table that could show 20 rows, but was populated with only 5 rows, clicking on the white space doesn’t select the last row. Normally, clicking on white space just brings focus to an object, or even closes an object. It just seemed different when I saw it the first time. I’m just being too picky. :slight_smile:

One other thing- working with Colby the other day, we found that the List.selectedIndex property change generates two events instead of one. I ran some more tests, and the only work-around I could find was binding the selectedIndex to a dynamic property and keying off that instead.

All in all, this is a great component. I needed to build a wizard, and I cascaded five of these list components side-by-side, and from the user’s perspective, it looks like a single dropdown menu where they can select different rows in each column, including multi-selections. It reduces clicks substantially, and will work great with a touch screen.

Ok, one more list qustion, and I promise I will never ask about a list again. :slight_smile:

How would I set the selected indices programatically in a multi-interval list? I can use setSelectedIndex() to set one item, but setSelectedIndices() doesn’t work.

Here is what I am trying to do: Let’s say a user has set up various recipes, and the list displays apple, banana, peach, and watermelon. He created a recipe called “recipe one”, selected apple and banana, and saved it. Later he wants to modify the recipe and add watermelon. What I would like to happen is that apple and banana are already selected when the list pops up, which is how it already works for the single selection list. Is this possible?

Sure, you can use the addSelectionInterval(start,end) function to affect the selection and add multi-selection intervals.

Hey, that’s perfect. Works like a charm.

Thanks again!

No problem!

I’m using the following code to populate a list, and although it works, I don’t quite understand exactly why the second “data = []” is required. If I comment it out, I get “IndexError: Row 0 doesn’t have the same number of columns as header list” at line 21. What exactly is happening?

Also, lines 6-8 are only used to clear the list. Is there a better way to do it?

Words = event.source.parent.getComponent('WordDictionary')
global gWD
gWD = {}
headers = ["Function"]

data = []
data.append([])
Words.data = fpmi.dataset.toDataSet(headers,'')
data = []

for k, v in gPD.items():
	WordDict = {}
	for i in v[5]:
		WordDict[i] = []
	gWD[v[1]]=WordDict

for k,v in gWD.items():
	data.append([k])

data.sort()
Words.data = fpmi.dataset.toDataSet(headers, data)

Whats happening is if you don’t reset the data sequence, you still have that empty row at the beginning, which doesn’t match the size of the other rows.

Why are you clearing it out at all? You’re setting the data on the last line anyhow - clearing it out up top doesn’t seem necessary.

Yeah, you’re right, I should have seen that. At one point my code was somehow concatenating the data on top of the list, so I started clearing the list first. Obviously when I started building the data set correctly, I didn’t have to clear it anymore.

Lets say I have a report i want to run. I have a List component that has it’s data bound to a query to select all “Recipes” from a table. Now I want to select MULTIPLE recipes. I also select a time range from another component. NOW i want to query recipes table for that time range and where Recipe = “SelectedValues” (so to speak). I already have it working for selecting ONE recipe in the list, but how do i do it for MULTIPLE intervals?

I found this in the HELP

# Loop through the selected values, doing something with them
list = event.source.parent.getComponent("MyList")
selected = list.getSelectedValues()
for value in selected:
    print value 

Thats fine for seeing the selected values in the CONSOLE LOL, but how would i pass it to a dynamic property??

Chris,

Assuming your SQL query will ultimately look something like this:

SELECT RecipeID, RecipeDate, Name, Description
WHERE RecipeID IN (0, 1, 15, 20, 211) AND RecipeDate BETWEEN ‘20091101’ AND ‘20091112’

You will need to iterate over the selected items in the list component and add each selected RecipeID to a python list. You would then convert the list to a comma separated list using a stirng join. You would then use the comma separated list to construct your query. You would then use the runQuery method to hit the database.

The following is pseudo-code for this:

#Use list comprehension to iterate over selected IDs and create a python list selectedIDs = ['%s' % id for id in listComponent.data.IDColumn] inClause = ','.join(selectedIDs) query = "SELECT RecipeID, RecipeDate, Name, Description WHERE RecipeID IN (%s) AND RecipeDate BETWEEN '20091101' AND '20091112'" % inClause results = fpmi.db.runQuery(query)

Ok, I believe I understand most of this. Except this part:

selectedIDs = ['%s' % id for id in listComponent.data.IDColumn]
inClause = ','.join(selectedIDs)

Here is what one query MIGHT look like:

SELECT Recipe, t_stamp
FROM Recipe
WHERE Recipe IN ('62886AXA.001', '44246AMA.017')
AND t_stamp
BETWEEN '2009-11-01 00:00:00' AND '2009-11-12 00:00:00'

And this works. I’m just not sure how to get the

WHERE Recipe IN ('62886AXA.001', '44246AMA.017')

How do i [quote]You will need to iterate over the selected items in the list component and add each selected RecipeID to a python list. You would then convert the list to a comma separated list using a stirng join. [/quote]

There are a couple of ways to get a comma seperated list. If you don’t need to sort the list and don’t need to reference it anywhere else, you can just build it directly from your results set, i.e.:

[code]
results = fpmi.db.runQuery(“Select Product from Products where Product != ‘’”)
csl = ‘’ #Comma seperated list
for i in results:
csl+=i[0]+’,’

print csl[/code]

You may have to strip the trailing comma if it breaks your code somewhere else, but I haven’t needed to.

If you want to put it in a python list first as Mickey describes, this would work:

results = fpmi.db.runQuery("Select Product from Products where Product!=''")
pl = [] #Python List
for i in results:
	pl.append(i[0])

csl = ','.join(pl)
print csl

is there any way to have a list, and based on “PROPERTY CHANGE” within the “Configure actions” have it run the code

[code]#Use list comprehension to iterate over selected IDs and create a python list
selectedIDs = [’%s’ % id for id in listComponent.data.IDColumn]
inClause = ‘,’.join(selectedIDs)
query = “SELECT RecipeID, RecipeDate, Name, Description WHERE RecipeID IN (%s) AND RecipeDate BETWEEN ‘20091101’ AND ‘20091112’” % inClause
results = fpmi.db.runQuery(query)

[/code]

But instead of doing a query, I want to send the “query =” to a dynamic property that is a string.

Chris,

[quote=“chris_d_sanders”]Ok, I believe I understand most of this. Except this part:

selectedIDs = ['%s' % id for id in listComponent.data.IDColumn]
inClause = ','.join(selectedIDs)

Here is what one query MIGHT look like:

SELECT Recipe, t_stamp
FROM Recipe
WHERE Recipe IN ('62886AXA.001', '44246AMA.017')
AND t_stamp
BETWEEN '2009-11-01 00:00:00' AND '2009-11-12 00:00:00'

And this works. I’m just not sure how to get the

WHERE Recipe IN ('62886AXA.001', '44246AMA.017')

How do i [quote]You will need to iterate over the selected items in the list component and add each selected RecipeID to a python list. You would then convert the list to a comma separated list using a stirng join. [/quote][/quote]
I’m sorry, my suggestion was a little cryptic and didn’t have a lot of explanation. I’ll try to explain it better.

The line selectedIDs = ['%s' % id for id in listComponent.data.IDColumn] is a list comprehension. At first, they’re a little cryptic but they are quite powerful. The basic purpose of a list comprehension is to apply an expression to a list (more technically, an iterative item such as a list or tuple), concatenating the results into another list. It’s sort of an abbreviated for or while loop. List comprehensions also have an optional “if” clause that can limit which items in the iterative item will have the expression applied. (See this for more discussion: http://books.google.com/books?id=VnGkf92gQh4C&pg=PA58&lpg=PA58&dq=jython+list+comprehension&source=bl&ots=y1G54gg6fM&sig=gmJ9BegCd5oF70CPjFO1SUdDctY&hl=en&ei=hewCS56DD8utlAeZveXcAQ&sa=X&oi=book_result&ct=result&resnum=6&ved=0CBkQ6AEwBQ#v=onepage&q=jython%20list%20comprehension&f=false)

Dissecting the line, the beginning and ending square brackets define the start and end of the list comprehension. The code before the ‘for’ is the expression that gets applied to each item in the iterative item following the ‘for’.

In my pseudo-code, I made the assumption that the ids were integers which needed to be converted to strings. So the purpose of the list comprehension was to convert the integers to strings. The “’%s’ % id” simply applied the % operator to each id in the list of ids.

But it looks like the ids are alphanumeric strings already and therefore would not need to be converted. You don’t need the list comprehension in your particular case.

The line “inClause = ‘,’.join(selectedIDs)” simply generates a comma separated list of the ids. So if selectedIDs = [‘62886AXA.001’, ‘44246AMA.017’], it would generate the string “‘62886AXA.001’, ‘44246AMA.017’”. I prefer to use the string join method because one doesn’t have to worry about any trailing commas as Step7 pointed out in his example.

Regarding your question about assigning the query to a dynamic property: You can assign the resulting query string to a dynamic property. You don’t have to use it in a query directly. Your script would end with something like this:

event.source.parent.DynamicProperty = query The exact syntax for the dynamic property reference will depend on where it is defined and from which component the event was generated.

The following assumes that you’re firing a script from an event. But is you’re wanting to generate the query with a FPMI expression, that’s a different ball of wax which I don’t have time to address right now. If that’s the case, just let me know and I, or someone else, will work up an example of that later.

MickeyBob,

Thanks for the reply… I actually figured it out before you posted LOL

list = event.source.parent.getComponent("Recipe List")
selected = list.getSelectedValues()
selectedIDs = ['%s' % id for id in selected]
inClause = "' ,'".join(selectedIDs)
query = "('%s')" % inClause
event.source.parent.RecipeINclause = query

But I wasn’t SURE what this selectedIDs = ['%s' % id for id in selected] was doing.

I don’t think you should have the single quotes in the query="(’%s’)" % inClause. That will give you an extra single quote at the beginning and one at the end. I think it shoud be this:

list = event.source.parent.getComponent("Recipe List") selected = list.getSelectedValues() selectedIDs = ['%s' % id for id in selected] inClause = " ,".join(selectedIDs) query = "(%s)" % inClause event.source.parent.RecipeINclause = query

[Edit]I am wrong - your previous version is correct. :thumb_right: [/Edit]

Now I have it down to this:

list = event.source.parent.getComponent("Recipe List")
selected = list.getSelectedValues()
inClause = "' ,'".join(selectedIDs)
query = "('%s')" % inClause
event.source.parent.RecipeINclause = query

Thanks Mickey… I tell you what, the more we do with this stuff at the plant the MORE I learn…

And it’s amazing how many things become possible when you figure out just a few lines of code.

You’re AWESOME!!!

Chris,

Thanks for the complement but I’m not so awesome, it’s FPMI that’s awesome.

The IA guys were either really insightful or dang lucky to realize how to leverage the simplicity and elegance of the Python/Jython language and the power of all those Java libraries. I am frequently amazed at how much can get done with so little code.