使用PySide清理Maya中的可停靠窗口 [英] Dockable window in Maya with PySide clean up

查看:158
本文介绍了使用PySide清理Maya中的可停靠窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个可以停驻在Maya主ui中的工具,但是我想不出一种方法在关闭它后对其进行清理.问题是,如果我创建该工具的多个实例,然后将其拖动到适当的位置以将其停靠,则在我右键单击Maya的窗口时,它们将全部显示.工具关闭后如何正确清理?

I created a tool that is able to dock in Maya's main ui, but I can't figure out a way to clean it up once it closes. The problem is if I create multiple instances of the tool then drag it in place to dock it, they will ALL show up when I right-click on Maya's window. How do I properly clean these up when the tool closes?

我已经尝试过cmds.deleteUIQObject.deleteLater(),充其量我只能清除该工具的内容,但它在Maya中仍然存在.这是到目前为止我所拥有的示例:

I already tried cmds.deleteUI, QObject.deleteLater() and at best I can only clear the tool's contents, but it will still exist in Maya. Here's an example of what I have so far:

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()

推荐答案

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

After digging around mayaMixin.py I managed to get a working solution with the behavior I'm after! The idea is that you need to dig through Maya's main window and delete any instances of it there.

关闭窗口或创建新实例后,以下示例将彻底删除所有实例.停靠或浮动都没关系,似乎可以正常工作.如果您不希望在停靠时关闭该行为,也可以随时对其进行调整.我在代码中留下了很多注释,因为那里有很多陷阱".

The example below will cleanly delete any instances once the window is closed or a new instance is created. It doesn't matter if it's docked or floating, it seems to work ok. You could always tweak the behavior too if you don't want it to delete if it's closed while being docked. I left many comments in the code as there was a lot of "gotchas".

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的环境了.希望对您有帮助!

With this it's no longer polluting Maya's environment anymore. Hope it helps!

这篇关于使用PySide清理Maya中的可停靠窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆