I'm learning how to build UI for maya in native python,(not Tkinter). the following code works just fine, creates a window with a button which when pressed prints 'bar' to the history output:
import maya.cmds as cmds
cmds.window(title='Basic UI')
cmds.columnLayout()
foo = 'bar'
cmds.button(label = 'foobar', command = 'print(foo)')
cmds.showWindow()
But if i put the same code in a function buildIt():
import maya.cmds as cmds
def buildIt():
cmds.window(title='Basic UI')
cmds.columnLayout()
foo = 'bar'
cmds.button(label = 'foobar', command = 'print(foo)')
cmds.showWindow()
buildIt()
The window builds fine but upon activating the button I get:
Error: NameError: file <maya console> line 1: name 'foo' is not defined
What is happening here? And how do I fix it?
When you run the first sample in the listener, foo
is defined in the global scope so it's available when the callback fires. In the second example it's defined in the scope of the function -- so it's not available when the callback fires in the global scope.
This will work:
import maya.cmds as cmds
def buildIt():
cmds.window(title='Basic UI')
cmds.columnLayout()
foo = 'bar'
def print_foo(*_):
print foo
cmds.button(label = 'foobar', command = print_foo)
cmds.showWindow()
buildIt()
The difference here is that we pass the function print_foo
directly, not as a string. So, Maya captures its value when the button is created and saves it (this is known as a closure, and it's super useful). This ensures that the function can be used when the callback is actually used.
In general, avoid using the string version of callbacks -- they are a holdover from MEL and they always result in exactly the problem you're seeing.
More detail here