【问题标题】:Dockable window in Maya with PySide clean upMaya 中使用 PySide 清理的可停靠窗口
【发布时间】:2015-11-06 09:04:29
【问题描述】:

我创建了一个能够停靠在 Maya 主 ui 中的工具,但我想不出在它关闭后清理它的方法。问题是如果我创建了该工具的多个实例,然后将其拖动到位以停靠它,当我右键单击 Maya 的窗口时,它们都会显示出来。工具关闭时如何正确清理这些?

我已经尝试过cmds.deleteUIQObject.deleteLater(),最多只能清除工具的内容,但它仍然存在于 Maya 中。这是我到目前为止的一个例子:

from shiboken import wrapInstance
from PySide import QtGui, QtCore
from maya import OpenMayaUI as OpenMayaUI
from maya.app.general.mayaMixin import MayaQWidgetDockableMixin

class Window(MayaQWidgetDockableMixin, QtGui.QWidget):
    def __init__(self, parent = None):
        super(self.__class__, self).__init__(parent = parent)
        mayaMainWindowPtr = OpenMayaUI.MQtUtil.mainWindow() 
        self.mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QtGui.QWidget) 
        self.setWindowFlags(QtCore.Qt.Window)

        if cmds.window('myTool', q = True, ex = True):
            cmds.deleteUI('myTool')

        self.setObjectName('myTool')

        self.setWindowTitle('My tool')
        self.resize(200, 200)

        self.myButton = QtGui.QPushButton('TEMP')

        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.myButton)
        self.setLayout(self.mainLayout)

    def dockCloseEventTriggered(self):
        self.deleteLater()

    def run(self):
        self.show(dockable = True)

myWin = Window()
myWin.run()

【问题讨论】:

  • 抱歉,我无法重现您的问题。如果我运行您的脚本,我可以以正确的方式拖动、停靠、取消停靠和关闭多个实例。您使用的是什么版本的 Maya?
  • 另一件事:如果你的代码中有if cmds.window('myTool', q = True, ex = True): cmds.deleteUI('myTool'),你不应该运行多个Window实例!
  • 也许我没有正确解释。我也可以运行、停靠、取消停靠和关闭多个实例。假设您创建了多个实例并将每个实例停靠到频道框/属性编辑器,然后关闭它们。右键单击通道框/属性编辑器窗口的标题,它会在那里显示一堆“我的工具”复选框!这是我无法清除的。
  • ^ erm no.. 一次不应该有多个实例。应该只有一个实例,这就是为什么它会尝试删除前一个实例。
  • 好的,我明白了。我也尝试过使用self.setAttribute(QtCore.Qt.WA_DeleteOnClose)self.setParent(None),但只删除了dockwidget 内容。如果我找到解决方案,我会告诉你

标签: python pyside maya


【解决方案1】:

在研究了 mayaMixin.py 之后,我设法找到了一个具有我所追求的行为的有效解决方案!这个想法是您需要挖掘 Maya 的主窗口并删除其中的所有实例。

一旦关闭窗口或创建新实例,下面的示例将彻底删除所有实例。不管它是停靠还是浮动,它似乎都可以正常工作。如果您不希望它在停靠时关闭,您也可以随时调整行为。我在代码中留下了很多 cmets,因为有很多“陷阱”。

from shiboken import wrapInstance
from PySide import QtGui, QtCore
from maya import OpenMayaUI as OpenMayaUI
from maya.app.general.mayaMixin import MayaQWidgetDockableMixin
from maya.OpenMayaUI import MQtUtil

class MyWindow(MayaQWidgetDockableMixin, QtGui.QDialog):
    toolName = 'myToolWidget'

    def __init__(self, parent = None):
        # Delete any previous instances that is detected. Do this before parenting self to main window!
        self.deleteInstances()

        super(self.__class__, self).__init__(parent = parent)
        mayaMainWindowPtr = OpenMayaUI.MQtUtil.mainWindow() 
        self.mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QtGui.QMainWindow)
        self.setObjectName(self.__class__.toolName) # Make this unique enough if using it to clear previous instance!

        # Setup window's properties
        self.setWindowFlags(QtCore.Qt.Window)
        self.setWindowTitle('My tool')
        self.resize(200, 200)

        # Create a button and stuff it in a layout
        self.myButton = QtGui.QPushButton('My awesome button!!')
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addWidget(self.myButton)
        self.setLayout(self.mainLayout)

    # If it's floating or docked, this will run and delete it self when it closes.
    # You can choose not to delete it here so that you can still re-open it through the right-click menu, but do disable any callbacks/timers that will eat memory
    def dockCloseEventTriggered(self):
        self.deleteInstances()

    # Delete any instances of this class
    def deleteInstances(self):
        mayaMainWindowPtr = OpenMayaUI.MQtUtil.mainWindow() 
        mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QtGui.QMainWindow) # Important that it's QMainWindow, and not QWidget/QDialog

        # Go through main window's children to find any previous instances
        for obj in mayaMainWindow.children():
            if type( obj ) == maya.app.general.mayaMixin.MayaQDockWidget:
                #if obj.widget().__class__ == self.__class__: # Alternatively we can check with this, but it will fail if we re-evaluate the class
                if obj.widget().objectName() == self.__class__.toolName: # Compare object names
                    # If they share the same name then remove it
                    print 'Deleting instance {0}'.format(obj)
                    mayaMainWindow.removeDockWidget(obj) # This will remove from right-click menu, but won't actually delete it! ( still under mainWindow.children() )
                    # Delete it for good
                    obj.setParent(None)
                    obj.deleteLater()        

    # Show window with docking ability
    def run(self):
        self.show(dockable = True)

myWin = MyWindow()
myWin.run()

有了这个,它就不再污染 Maya 的环境了。希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多