Tuesday, February 24, 2009

More Lambda and GUI fun

Just tripped over an interesting problem with the lambda stuff I shared in the last post. It's just peachy if you're passing a literal value:

# other code omitted for brevity
mc.button(l="click me", c=lambda x:colorMe("Purple"))

However, if you're creating a collection of controls using a loop, it no worky correctly:

names = ["me", "you", "him"]
for name in names:
mc.button(l=name, c=lambda x:nameMe(name)

In this example, no matter which button you click, it will pass "him".

I tried a number of ways to get around this, and wasn't successful until I revisited the page that flipped the lambda light switch for me. The second example on that page shows how to create a "lambda factory" of sorts. In the context of the loop situation, the factory serves to isolate the creation of the lambda function from the loop. While the factory function was a standalone item in the example on that page, it would be convenient to nest said factory inside the same function/method that contains the loop. Here's a more fleshed-out example:

import maya.cmds as mc

def addButtons (names):
# here's the factory function
def factory (nm):
return lambda x:showName(nm)

# and here's our loop
for name in names:
mc.button(l=name, c=factory(name))

It's a bit more extra code than I'd hoped for, but it's only needed when using the lambda technique inside a loop, and still allows me to keep the target functions/methods clean by avoiding nesting.

1 comment:

kattkieru said...

Just wanted to give you a big "Thanks!" for writing these up. I hadn't thought to use Lambda functions in UI code at all; this is a really interesting technique, and it's got me thinking about a lot of new tricks.

A lot of folks in the industry keep info like this to themselves. It's nice that there are still people out there excited to learn and to spread what they've learned to others. Thanks again!