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

如何让Maya脚本UI置于主窗口上层且不遮挡系统弹窗?

解决Maya Qt UI遮挡内置对话框及独立显示问题

核心修改思路

  • 绑定Maya主窗口为父容器,让UI随Maya窗口状态同步显示/隐藏
  • 替换全局置顶策略,改用Qt.Tool窗口标志,既保持UI在Maya上方,又不拦截Maya模态对话框的焦点
  • 日志窗口绑定脚本UI为父,保证窗口层级同步

修改后的完整代码

import sys
import os
import logging
from PySide2 import QtCore, QtGui, QtWidgets
import maya.cmds as cmds
from modelCheckerExporter import MayaSceneTools

# Add the directory containing the script to the Python path
script_dir = os.path.dirname(__file__)
if script_dir not in sys.path:
    sys.path.append(script_dir)

# Change current working directory to the script's directory
os.chdir(script_dir)

def get_maya_main_window():
    """获取Maya主窗口的Qt指针"""
    for widget in QtWidgets.QApplication.topLevelWidgets():
        if widget.objectName() == "MayaWindow":
            return widget
    return None

class QTextEditLogger(QtWidgets.QMainWindow):
    def __init__(self, log_file_path, parent=None):
        super(QTextEditLogger, self).__init__(parent)
        self.setWindowTitle("Log Output")
        self.setGeometry(100, 100, 850, 400)

        self.log_file_path = log_file_path

        self.text_edit = QtWidgets.QTextEdit(self)
        self.text_edit.setReadOnly(True)
        self.setCentralWidget(self.text_edit)

        self.update_timer = QtCore.QTimer(self)
        self.update_timer.timeout.connect(self.update_log_display)
        self.update_timer.start(1000)  # Update every second

    def update_log_display(self):
        with open(self.log_file_path, 'r') as log_file:
            log_data = log_file.read()
            self.text_edit.setPlainText(log_data)

class model_checker_UI(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(model_checker_UI, self).__init__(parent)
        self.setup_ui()
        # 替换全局置顶为Tool窗口标志:依附父窗口,保持在Maya上方,不拦截模态对话框
        self.setWindowFlags(QtCore.Qt.Tool | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint)

        self.log_window = None
        self.log_file_path = "model_checker.log"

        # Initialize logger
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)
        self.clear_log_handlers()
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        file_handler = logging.FileHandler(self.log_file_path, mode='w')  # Overwrite mode
        file_handler.setFormatter(formatter)
        self.logger.addHandler(file_handler)

    def clear_log_handlers(self):
        if self.logger.hasHandlers():
            self.logger.handlers.clear()
    
    def setup_ui(self):
        self.setWindowTitle("WH Model Checker 3.0")
        self.setObjectName("WHModelCheckerID")
        self.setMinimumSize(265, 450)
        self.setMaximumSize(365, 450)
        self.resize(265, 450)

        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.setAlignment(QtCore.Qt.AlignTop)
        self.main_layout.setContentsMargins(5, 5, 5, 5)
        self.main_layout.setSpacing(5)
        self.setLayout(self.main_layout)

        self.headder_layout = QtWidgets.QVBoxLayout()
        self.headder_layout.setAlignment(QtCore.Qt.AlignTop)
        self.headder_layout.setContentsMargins(3, 3, 3, 3)
        self.headder_layout.setSpacing(2)
        self.main_layout.addLayout(self.headder_layout)

        self.top_title = QtWidgets.QLabel("Check for Errors:")
        self.top_title.setAlignment(QtCore.Qt.AlignHCenter)
        self.title_font_A = self.top_title.font()
        self.title_font_A.setBold(True)
        self.title_font_A.setPointSize(12)
        self.top_title.setFont(self.title_font_A)
        self.headder_layout.addWidget(self.top_title)

        self.show_log_window()

    def show_log_window(self):
        """创建并显示日志窗口,绑定当前UI为父窗口"""
        if not self.log_window or not self.log_window.isVisible():
            self.log_window = QTextEditLogger(self.log_file_path, parent=self)
            self.log_window.show()


def main():
    if cmds.window("WHModelCheckerID", exists=True):
        cmds.deleteUI("WHModelCheckerID", window=True)

    if cmds.windowPref("WHModelCheckerID", exists=True):
        cmds.windowPref("WHModelCheckerID", remove=True)

    # 获取Maya主窗口作为父容器
    maya_main_window = get_maya_main_window()
    global myUI
    myUI = model_checker_UI(parent=maya_main_window)
    myUI.show()

main()

修改说明

  1. 获取Maya主窗口:新增get_maya_main_window函数,遍历Qt顶级窗口找到Maya主窗口,作为脚本UI的父容器
  2. 调整窗口标志:移除QtCore.Qt.WindowStaysOnTopHint,改用QtCore.Qt.Tool,该标志的特性是:
    • 始终保持在父窗口(Maya主窗口)上方
    • 不会拦截父窗口弹出的模态对话框,Maya内置对话框会自动显示在脚本UI上方
  3. 日志窗口绑定父级:show_log_window方法中创建日志窗口时传入当前UI作为父,确保日志窗口随主UI同步隐藏/显示
  4. UI初始化传参:main函数中创建UI时传入Maya主窗口指针,完成父子绑定

优化后效果

  • Maya弹出的对话框(如保存、导入、选项窗口)会优先获得焦点并显示在脚本UI上方
  • 隐藏Maya主窗口时,脚本UI和日志窗口会自动隐藏
  • 脚本UI始终保持在Maya主窗口上方,不会被Maya主窗口覆盖

内容的提问来源于stack exchange,提问作者Valeriya Fedoseeva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:15:04