Maya/Python 如何在UI窗口关闭时执行指定命令
Maya窗口关闭时自动销毁scriptJob实现方案
核心逻辑是将销毁scriptJob的逻辑绑定到窗口的关闭回调事件中,根据你使用的UI实现方式,有两种常用落地方案:
方案1:使用maya.cmds原生UI实现
cmds.window提供了closeCommand参数,可直接绑定窗口关闭时触发的回调函数,示例代码如下:
import maya.cmds as cmds # 存储scriptJob的唯一ID,用于后续销毁 script_job_id = None def window_close_callback(): global script_job_id # 销毁前先判断scriptJob是否存在,避免重复关闭时报错 if script_job_id and cmds.scriptJob(exists=script_job_id): cmds.scriptJob(kill=script_job_id, force=True) # 示例:创建监听选择变化的scriptJob script_job_id = cmds.scriptJob(event=["SelectionChanged", lambda: print("选择已更新")], permanent=False) # 创建窗口时绑定关闭回调 if cmds.window("custom_tool_win", exists=True): cmds.deleteUI("custom_tool_win") cmds.window("custom_tool_win", title="自定义工具", closeCommand=window_close_callback) cmds.columnLayout(adjustableColumn=True) cmds.text(label="关闭窗口将自动销毁后台scriptJob") cmds.showWindow("custom_tool_win")
方案2:使用PySide2/PyQt实现自定义Qt窗口
如果是基于Qt框架开发的自定义窗口,直接重写closeEvent方法即可,不需要依赖Maya原生UI的参数,灵活性更高,示例代码如下:
from PySide2 import QtWidgets import maya.cmds as cmds import maya.OpenMayaUI as omui from shiboken2 import wrapInstance def get_maya_main_window(): main_win_ptr = omui.MQtUtil.mainWindow() return wrapInstance(int(main_win_ptr), QtWidgets.QWidget) class CustomToolWindow(QtWidgets.QDialog): def __init__(self, parent=get_maya_main_window()): super().__init__(parent) self.setWindowTitle("Qt自定义工具") self.resize(300, 150) # 将scriptJobID存储为实例属性,避免全局变量冲突 self.script_job_id = None # 初始化scriptJob self.script_job_id = cmds.scriptJob(event=["SelectionChanged", lambda: print("选择已更新")], permanent=False) # 基础布局 layout = QtWidgets.QVBoxLayout(self) layout.addWidget(QtWidgets.QLabel("关闭窗口将自动销毁后台scriptJob")) def closeEvent(self, event): # 关闭窗口前先销毁scriptJob if self.script_job_id and cmds.scriptJob(exists=self.script_job_id): cmds.scriptJob(kill=self.script_job_id, force=True) # 执行默认关闭逻辑 event.accept() # 窗口调用逻辑 if __name__ == "__main__": # 避免重复创建窗口实例 try: custom_win.close() custom_win.deleteLater() except: pass custom_win = CustomToolWindow() custom_win.show()
避坑提示
- 创建scriptJob时不要设置
permanent=True,否则无法被常规kill操作删除 - 不要将scriptJob的
parent参数绑定到Maya主窗口,否则只有Maya完全关闭时才会销毁scriptJob - 如果使用停靠窗口,可使用
cmds.dockControl()的closeCommand参数绑定回调,逻辑和普通原生窗口一致 - 测试时可执行
cmds.scriptJob(listJobs=True)打印所有运行中的scriptJob,确认关闭窗口后对应任务已被清除
内容的提问来源于stack exchange,提问作者Knkemora
相关产品推荐
相关产品推荐

