You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:57:00