Maya Python脚本编辑器运行正常,货架按钮执行提示scanImp函数未定义
问题根因
你遇到的报错核心原因是Maya UI控件的字符串回调机制的作用域问题:
- 你在
iconTextButton的c(点击回调)参数里传入的是字符串格式的scanImp("xxx"),Maya执行这类字符串回调时,只会从全局命名空间中查找对应的函数 - 你直接在脚本编辑器运行代码时,整个脚本的作用域和全局命名空间是打通的,定义的
scanImp函数能被正常找到 - 你通过货架按钮加载外部脚本时,脚本默认运行在独立的模块作用域内,你定义的
scanImp函数没有暴露到全局命名空间,Maya执行回调时就会提示函数未定义
可行解决方案
方案1:将回调函数注册到全局命名空间
在脚本开头导入__main__模块,定义完scanImp函数后将其绑定到__main__的属性上,就能让Maya全局识别到该函数:
from maya import cmds import os import __main__ # 新增导入 imagePath = 'C:/IMAGES/_ICONS_/' def scanImp(*args): print args[0] + ' ' + ' was pushed.' ImgNmNoExt = args[0].split('.') ScanBtnPath = imagePath + ImgNmNoExt[0] print 'the directory is:' + ' ' + ScanBtnPath # 新增:将函数注册到全局 __main__.scanImp = scanImp # 如果还有scan_light函数也做同样注册 # __main__.scan_light = scan_light # 剩余创建窗口的代码保持不变 if cmds.window('window1', q=1, ex=1): cmds.deleteUI('window1') cmds.window('window1', t='SCAN IMPORTER', mb=1) cmds.gridLayout(cw=150, w=500, nc=8, h=800, ch=150) getImgList = os.listdir(imagePath) for i in getImgList: scanBtn = cmds.iconTextButton(i=imagePath + i, c='scanImp("' + i + '")', dcc='scan_light("' + i + '")') cmds.showWindow('window1')
方案2:使用非字符串形式的回调(更推荐)
直接将函数对象作为回调传入,避免依赖全局命名空间,同时要注意处理循环变量的闭包问题,用lambda的默认参数捕获当前循环的图片名:
# 创建按钮的部分修改为以下代码 for i in getImgList: # 第一个下划线参数接收Maya按钮默认传入的布尔参数 scanBtn = cmds.iconTextButton( i=imagePath + i, c=lambda _, img=i: scanImp(img), dcc=lambda _, img=i: scan_light(img) )
方案3:按模块规范组织代码
将你的脚本命名为scan_importer.py放到已加入Maya脚本路径的目录下,货架按钮的执行代码改为先导入模块再调用窗口创建函数:
# 货架按钮执行的代码 import scan_importer scan_importer.create_window()
同时修改你的脚本代码,把回调的字符串改为带模块前缀的形式:
for i in getImgList: scanBtn = cmds.iconTextButton(i=imagePath + i, c='scan_importer.scanImp("' + i + '")', dcc='scan_importer.scan_light("' + i + '")')
额外注意事项
你当前scanImp函数中用到的imagePath变量也和函数定义在同一个作用域,如果你后续拆分代码,需要注意保证该变量能被函数正常访问,建议封装成类或者作为函数参数传入,避免后续也出现变量未定义的问题。
内容的提问来源于stack exchange,提问作者XYZ_ABC_ZM
相关产品推荐
相关产品推荐

