Command flag in symbolButton keeps erroring for me

220 views
Skip to first unread message

likage

unread,
Mar 14, 2017, 1:20:13 AM3/14/17
to Python Programming for Autodesk Maya
I am trying out using maya symbolcheckbox and I run into a few issue. In my actual code, I have a 'add', 'remove' and 'clear' button and so if any of these 3 buttons are clicked onto, it will called its own functions. In my code, it was written something as follow:
self.btn_add = cmds.symbolButton( width=60, height=20, annotation='Add object(s)', image='add.xpm', command=lambda * args:self.btnCallback("add", "item_list") )

def uiListCallback(self, *args):
    mode
= args[0]
    text_list = args[1]
   
if mode == "add":
       
# do this
   
elif mode == "remove"
       
# do that

But when I tried to create a function for each action, I keep getting errors.
This is simple example, but it illustrates the problem I had.

However, if I execute the following code:
def greet():
   
print 'hello'

def main():
    cmds
.window()
    cmds
.columnLayout()
    cmds
.symbolCheckBox(image='circle.png', changeCommand=greet())
    cmds
.showWindow()
main
()

I will get `# Error: TypeError: file <maya console> line 9: Invalid arguments for flag 'changeCommand'.  Expected string or function, got NoneType # `

But if I did it in another way:
def greet():
   
print 'hello'

def main():
    cmds
.window()
    cmds
.columnLayout()
   
# () was added into greet under the command flag
    cmds
.symbolCheckBox(image='circle.png', command=greet())
    cmds
.showWindow()
main
()

While I get a popup, but as soon as I click on it, I will get this error - `# Error: greet() takes no arguments (1 given) # `

Where am I doing it wrong?

Alok Gandhi

unread,
Mar 14, 2017, 1:39:03 AM3/14/17
to python_in...@googlegroups.com
I will get `# Error: TypeError: file <maya console> line 9: Invalid arguments for flag 'changeCommand'.  Expected string or function, got NoneType # `
You need to pass the function object to change commands, currently you are passing the result of calling greet().

I think this should work for you:
import maya.cmds as cmds

def greet(value):
    print 'greet was called with value: {0}'.format(value)
    print 'hello'

def main():
    cmds.window()
    cmds.columnLayout()
    # () was added into greet under the command flag
    cmds.symbolCheckBox(image='circle.png', changeCommand=greet)
    cmds.showWindow()
main()

likage

unread,
Mar 14, 2017, 11:59:37 AM3/14/17
to Python Programming for Autodesk Maya
While it works for the example, I tried applying the same concept into my actual code, I am getting the errors..
self.btn_add = cmds.symbolButton( width=60, height=20, annotation='Add object(s)', image='add.xpm', command=self.add_btn_callback("item_list") )

def add_btn_callback(self, "list"):
   
# Do the exec when add button is clicked

Robert White

unread,
Mar 14, 2017, 12:04:17 PM3/14/17
to Python Programming for Autodesk Maya
Try wrapping it in a lambda?
self.btn_add = cmds.symbolButton( width=60, height=20, annotation='Add object(s)', image='add.xpm', command=lambda *x: self.add_btn_callback("item_list") )

likage

unread,
Mar 14, 2017, 12:12:08 PM3/14/17
to Python Programming for Autodesk Maya
Try wrapping it in a lambda?
self.btn_add = cmds.symbolButton( width=60, height=20, annotation='Add object(s)', image='add.xpm', command=lambda *x: self.add_btn_callback("item_list") )

Okay, so it works. And my question is why? 

Robert White

unread,
Mar 14, 2017, 1:12:34 PM3/14/17
to Python Programming for Autodesk Maya
Because maya expects you to pass either a string, or a callable to the command flag. 
When you don't wrap the function in a lambda, you're calling the function, and passing the result to the command flag.

Justin Israel

unread,
Mar 14, 2017, 2:26:29 PM3/14/17
to Python Programming for Autodesk Maya
Python has a concept called "first class functions". It means a function is an object just like anything else, like strings and lists. They can be passed around as args and saved as references in variables. Callbacks are implemented by have a function passed as an object so that the function can be saved and called later. 

def hello():
    print "hello" 

# call function immediately 
hello() 

# assign function to variable
fn = hello
fn() 

Note that if you don't return a value from a function, the return value is implicitly None. This will explain strange errors about the type when you call the function instead of passing it as a first class function. 

val = hello() 
print type(val) 

For more information here is a tutorial and a general wiki:



Justin 


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/4f0ec7aa-064a-415d-a295-0a1de7f6e430%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

likage

unread,
Mar 14, 2017, 8:40:50 PM3/14/17
to Python Programming for Autodesk Maya
Interesting... Thanks for the information, guys!
Never thought that with a simple example that I have used, it can failed almost immediately.

From the flags, though it mentions of `script` I had assumed that it will worked with a normal method too..

Justin Israel

unread,
Mar 14, 2017, 8:49:31 PM3/14/17
to python_in...@googlegroups.com
On Wed, Mar 15, 2017 at 1:40 PM likage <dissid...@gmail.com> wrote:
From the flags, though it mentions of `script` I had assumed that it will worked with a normal method too..

This refers to the ability to pass script logic in string form. In MEL there are no first class functions so your only option is to pass a string with MEL script to run. In python you can either pass Python script to be evaluated, or a callable object.
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Michael Boon

unread,
Mar 15, 2017, 10:35:08 PM3/15/17
to Python Programming for Autodesk Maya
Lambdas are particularly confusing, too. Your original attempt
command=lambda *x: self.add_btn_callback("item_list")
doesn't actually call the function add_btn_callback, even though it looks like it does. It creates a new function that will call add_btn_callback later.

I prefer partial instead, because it seems clearer to me what is happening. partial is similar to lambda. It creates a new function that will call your function with given arguments:
from functools import partial
...
command
=partial(add_btn_callback, "item_list")

And I should warn you: right now your argument is a constant string "item_list". Things get even weirder if you have arguments whose values might be different when the button is clicked than they are now.



On Wednesday, 15 March 2017 11:49:31 UTC+11, Justin Israel wrote:
On Wed, Mar 15, 2017 at 1:40 PM likage <dissid...@gmail.com> wrote:
From the flags, though it mentions of `script` I had assumed that it will worked with a normal method too..

This refers to the ability to pass script logic in string form. In MEL there are no first class functions so your only option is to pass a string with MEL script to run. In python you can either pass Python script to be evaluated, or a callable object.
 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages