Help assigning button cmd args in loop

465 views
Skip to first unread message

PixelMuncher

unread,
Jan 11, 2011, 11:36:17 AM1/11/11
to python_inside_maya
Hi all:
I know this has been covered b4, but I'm still having trouble with it.
I have a UI which loads user-defined attrs (sliders) into an
interface. These attrs are drivers for SDKs, so I have buttons to
select the attrs so I can update the driven keys. I have a button to
clear the panel (deleteUI) and then I'm able to recreate it based on
the selection. Below is the function to recreate the slider panel,
but of course the args for the button commands don't work, and I don't
know how to fix it. I want to stick w/a Python-based solution.

Chad has a post at CGTalk for writing a callback class, but I don't
know how to call it inside my function.
http://forums.cgsociety.org/showthread.php?f=89&t=648707&highlight=args+loop

Help would be appreciated.

def fillUDPanel():
global sliderContainer
sel=cmds.ls(sl=1)
if len(sel) == 0:
mel.error("You must have an object selected!")

for obj in sel:
attributes=cmds.listAttr(obj, ud=1)
if not attributes :
print obj,'doesn\'t have obj user-defined atttrs.'
continue
cmds.setParent('frameBegin')
sliderContainer =
cmds.frameLayout('sliderFrame',collapsable=1,l=obj ,bs="etchedOut")
cmds.rowColumnLayout('sliderPanel', nc = 2, columnWidth=[(2, 40)])
for attr in attributes:
fullName=(str(obj) + "." + str(attr))
cmds.attrFieldSliderGrp(cw=(1, 90),at=fullName,cat=(1, 'left',
10))
cmds.button(l='Sel',w=20, command = lambda *args:
selectMe(fullName) )

PixelMuncher

unread,
Jan 11, 2011, 12:55:09 PM1/11/11
to python_inside_maya
and this is the command I'm trying to assign to the buttons:
def selectMe(who):
print 'selectMe:',who
cmds.select (who)

damon shelton

unread,
Jan 11, 2011, 1:18:40 PM1/11/11
to python_in...@googlegroups.com
with the use of lambda in a loop, the lambdas always wind up using the last argument defined of the loop

to get around this I do this:

cmds.button(l='Sel',w=20, command = lambda x, y = fullName:selectMe(y) )

assign your value to an argument of the lambda


Ofer Koren

unread,
Jan 11, 2011, 1:29:03 PM1/11/11
to python_in...@googlegroups.com
If you have pymel you should use the Callback class implemented there. It has better handling of errors and undos and whatnot.
If you don't have pymel you could just define this simple version and use it:

class Callback(object): def __init__(self, func, *args, **kwargs): self.func = func self.args = args self.kwargs = kwargs def __call__(self): return self.func( *self.args, **self.kwargs )


def fillUDPanel():
       global sliderContainer
       sel=cmds.ls(sl=1)
       if len(sel) == 0:
               mel.error("You must have an object selected!")

       for obj in sel:
               attributes=cmds.listAttr(obj,   ud=1)
               if not  attributes :
                       print obj,'doesn\'t have obj user-defined atttrs.'
                       continue
               cmds.setParent('frameBegin')
               sliderContainer = cmds.frameLayout('sliderFrame',collapsable=1,l=obj  ,bs="etchedOut")
               cmds.rowColumnLayout('sliderPanel', nc = 2, columnWidth=[(2, 40)])
               for attr in attributes:
                       fullName=(str(obj) + "." + str(attr))
                       cmds.attrFieldSliderGrp(cw=(1, 90),at=fullName,cat=(1, 'left', 10))
                       cmds.button(l='Sel',w=20, command = Callback(selectMe, fullName) )


PixelMuncher

unread,
Jan 11, 2011, 1:35:39 PM1/11/11
to python_inside_maya
Thanks so much. That has been driving me crazy all morning!

On Jan 11, 12:18 pm, damon shelton <damondshel...@gmail.com> wrote:
> with the use of lambda in a loop, the lambdas always wind up using the last
> argument defined of the loop
>
> to get around this I do this:
>
> cmds.button(l='Sel',w=20, command = lambda x, y = fullName:selectMe(y) )
>
> assign your value to an argument of the lambda
>
Message has been deleted

PixelMuncher

unread,
Jan 11, 2011, 2:08:08 PM1/11/11
to python_inside_maya
Thanks Oren:
I'm not familiar w/using classes, but I did try your suggestion.
Assuming that I unwrapped your Class correctly:
class Callback(object):
def __init__(self, func, *args, **kwargs):
self.func= func
self.args = args
self.kwargs = kwargs
def __call__(self):
return self.func( *self.args, **self.kwargs )

When run the script, I get this error:
# File "C:\Documents and Settings\Administrator\My Documents\maya
\myScripts\panelContentChange.py", line 125
# cmds.button(l='Sel',w=20, command =
*Callback(selectMe,fullName)* )
# ^
# SyntaxError: invalid syntax #
>                        cmds.button(l='Sel',w=20, command = *Callback(selectMe,
> fullName)* )
>
> - Oferwww.mrbroken.com
Message has been deleted

Matt Estela

unread,
Jan 11, 2011, 5:49:27 PM1/11/11
to python_in...@googlegroups.com
the 'partial' trick doesn't work for you?

import maya.cmds as cmds
from functools import partial

def myFunc(set,*args):
print 'you chose ', set

occSets = ['A','B','C','D']
for i in occSets():
cmds.menuItem(l=i, c=partial(myFunc,i))

On Wed, Jan 12, 2011 at 6:08 AM, PixelMuncher <pixel...@gmail.com> wrote:
> Thanks Oren:
> I'm not familiar w/using classes, but I did try your suggestion.
> Assuming that I unwrapped your Class correctly:

> class Callback(object):
>    def __init__(self, func, *args, **kwargs):

>        self.func= func


>        self.args = args
>        self.kwargs = kwargs
>    def __call__(self):
>        return self.func( *self.args, **self.kwargs )
>

> When run the script, I get this error:
> #   File "C:\Documents and Settings\Administrator\My Documents\maya
> \myScripts\panelContentChange.py", line 125

> #     cmds.button(l='Sel',w=20, command =


> *Callback(selectMe,fullName)* )
> #                                         ^
> # SyntaxError: invalid syntax #
>
> On Jan 11, 12:29 pm, Ofer Koren <kor...@gmail.com> wrote:

>>                        cmds.button(l='Sel',w=20, command = *Callback(selectMe,
>> fullName)* )
>>
>> - Oferwww.mrbroken.com
>>

>> On Tue, Jan 11, 2011 at 7:55 PM, PixelMuncher <pixeldr...@gmail.com> wrote:
>> > and this is the command I'm trying to assign to the buttons:
>> > def selectMe(who):
>> >    print 'selectMe:',who
>> >    cmds.select (who)
>>
>> > --
>> >http://groups.google.com/group/python_inside_maya
>>
>>
>

> --
> http://groups.google.com/group/python_inside_maya
>

Ofer Koren

unread,
Jan 12, 2011, 3:12:50 AM1/12/11
to python_in...@googlegroups.com
It looks like my highlighting that piece of text created asterisks (*)
on your end; they should just be removed:

...


cmds.button(l='Sel',w=20, command = Callback(selectMe, fullName) )

- Ofer
www.mrbroken.com


On Tue, Jan 11, 2011 at 9:08 PM, PixelMuncher <pixel...@gmail.com> wrote:
>
> Thanks Oren:
> I'm not familiar w/using classes, but I did try your suggestion.
> Assuming that I unwrapped your Class correctly:

> class Callback(object):
>    def __init__(self, func, *args, **kwargs):

>        self.func= func


>        self.args = args
>        self.kwargs = kwargs
>    def __call__(self):
>        return self.func( *self.args, **self.kwargs )
>

> When run the script, I get this error:
> #   File "C:\Documents and Settings\Administrator\My Documents\maya
> \myScripts\panelContentChange.py", line 125
> #     cmds.button(l='Sel',w=20, command =
> *Callback(selectMe,fullName)* )
> #                                         ^
> # SyntaxError: invalid syntax #
>
> On Jan 11, 12:29 pm, Ofer Koren <kor...@gmail.com> wrote:

> >                        cmds.button(l='Sel',w=20, command = *Callback(selectMe,
> > fullName)* )
> >
> > - Oferwww.mrbroken.com
> >

> > On Tue, Jan 11, 2011 at 7:55 PM, PixelMuncher <pixeldr...@gmail.com> wrote:
> > > and this is the command I'm trying to assign to the buttons:
> > > def selectMe(who):
> > >    print 'selectMe:',who
> > >    cmds.select (who)
> >
> > > --
> > >http://groups.google.com/group/python_inside_maya
> >
> >
>

> --
> http://groups.google.com/group/python_inside_maya

PixelMuncher

unread,
Jan 12, 2011, 5:32:06 PM1/12/11
to python_inside_maya
Ofer
The asterisks were a problem, but I also had to change the call
command to include more than 1 arg:
def __call__(self, *args):

Matt:
I've not encountered 'partial' before. It also worked. Is that
similar to a callback?

Thanks again for all the help.

Ofer Koren

unread,
Jan 13, 2011, 4:30:52 AM1/13/11
to python_in...@googlegroups.com
You're right, some gui callbacks are called with on or more parameter, forgot about that one.

"partial" is a built-in function that python provides for doing what this Callback class does. As I said, this Callback class (and the partial function) is very basic, and doesn't deal with some issues:
- Trying to Undo a gui event (for example a button-push) will not undo the entire action, rather fragments of it one at a time. The pymel Callback class takes care of that, wrapping the entire action into one undo-able piece.
- Tracebacks get polluted with this callback code, making it harder to identify the source of problems. The pymel Callback class takes care of that as well, restoring the tracebacks to their original form.

Reply all
Reply to author
Forward
0 new messages