如何让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()
修改说明
- 获取Maya主窗口:新增
get_maya_main_window函数,遍历Qt顶级窗口找到Maya主窗口,作为脚本UI的父容器 - 调整窗口标志:移除
QtCore.Qt.WindowStaysOnTopHint,改用QtCore.Qt.Tool,该标志的特性是:- 始终保持在父窗口(Maya主窗口)上方
- 不会拦截父窗口弹出的模态对话框,Maya内置对话框会自动显示在脚本UI上方
- 日志窗口绑定父级:
show_log_window方法中创建日志窗口时传入当前UI作为父,确保日志窗口随主UI同步隐藏/显示 - UI初始化传参:
main函数中创建UI时传入Maya主窗口指针,完成父子绑定
优化后效果
- Maya弹出的对话框(如保存、导入、选项窗口)会优先获得焦点并显示在脚本UI上方
- 隐藏Maya主窗口时,脚本UI和日志窗口会自动隐藏
- 脚本UI始终保持在Maya主窗口上方,不会被Maya主窗口覆盖
内容的提问来源于stack exchange,提问作者Valeriya Fedoseeva
相关产品推荐
相关产品推荐

