Skip to content

Instantly share code, notes, and snippets.

@Nixellion
Last active September 10, 2021 09:35
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Nixellion/f28051f1b53fee8b11a2fcd36ca244c3 to your computer and use it in GitHub Desktop.
Save Nixellion/f28051f1b53fee8b11a2fcd36ca244c3 to your computer and use it in GitHub Desktop.
Maya - Creating PySide windows in Maya 2014-2018+, with docking
'''
------------------------------------------------------------------------------------------------------------------------
# Maya 2017 PySide2 Docking Qt QMainWindow by Michael Davydov | https://github.com/Nixellion/
## https://www.michaeldavydov.com | https://www.nixes.ru
------------------------------------------------------------------------------------------------------------------------
This module aims to have functions and classes that you can use to create your own Maya UI, with support of Maya with
PySide and PySide2 (2014-2018+). Primary focus on dockable windows.
Major changes have been made in Maya version 2017, when it moved from Qt4\PySide to Qt5\PySide2.
I will update this file eventually with more functions and stuff.
------------------------------------------------------------------------------------------------------------------------
Honrable mentions of people who's work was used as part of this code, for inspiration or help:
- Lior Ben Horin https://gist.github.com/liorbenhorin/ - for starting code snippet, which showed how to start working with
workspaceControl.
- Guys from tech-artists.org\techart.online who helped with advice: http://discourse.techart.online/t/maya-dockable-windows-boilerplate-with-support-for-pyside2/9617/14
------------------------------------------------------------------------------------------------------------------------
To quickly adapt this code for youserlf do the following:
- Replace `log.debug` with `print`
- Retarget Qt.py imports for your project
Should work after that.
------------------------------------------------------------------------------------------------------------------------
'''
__author__ = "Michael Davydov https://www.michaeldavydov.com"
__version__ = "1.0.0"
# ----------------------------------------------------------------------------------------------------------------------
# Python standard modules
# ----------------------------------------------------------------------------------------------------------------------
import weakref
# ----------------------------------------------------------------------------------------------------------------------
# Maya modules
# ----------------------------------------------------------------------------------------------------------------------
import maya.cmds as cmds
import maya.OpenMayaUI as omui
from maya.app.general.mayaMixin import *
# ----------------------------------------------------------------------------------------------------------------------
# Shiboken
# ----------------------------------------------------------------------------------------------------------------------
try:
from shiboken2 import wrapInstance
except:
from shiboken import wrapInstance
# ----------------------------------------------------------------------------------------------------------------------
# Qt module - https://github.com/mottosso/Qt.py by Marcus Ottosson
# ----------------------------------------------------------------------------------------------------------------------
from BroTools.common.broqt.vendor.Qt import *
from BroTools.common.broqt.vendor.Qt.QtWidgets import *
from BroTools.common.broqt.vendor.Qt.QtGui import *
from BroTools.common.broqt.vendor.Qt.QtCore import *
# ----------------------------------------------------------------------------------------------------------------------
# Custom logging function with support of print-like comma-separated args and more
# ----------------------------------------------------------------------------------------------------------------------
from BroTools.common.debug import default_logger as log
# ----------------------------------------------------------------------------------------------------------------------
# Globals
# ----------------------------------------------------------------------------------------------------------------------
maya_version = int(cmds.about(v=True))
# ----------------------------------------------------------------------------------------------------------------------
# Classes
# ----------------------------------------------------------------------------------------------------------------------
class BroMainWindow_Dockable(MayaQWidgetDockableMixin, QMainWindow):
DOCK_LABEL_NAME = 'no name window' # Window display name
CONTROL_NAME = 'no_name_window' # Window unique object name
instances = list()
def __init__(self):
super(BroMainWindow_Dockable, self).__init__()
self.delete_instances()
self.__class__.instances.append(weakref.proxy(self))
# Not sure, but I suppose that we better keep track of instances of our window and keep Maya environment clean.
# So we'll remove all instances before creating a new one.
if maya_version >= 2017:
if cmds.window(self.CONTROL_NAME + "WorkspaceControl", ex=True):
log.debug("Removing", self.CONTROL_NAME + "WorkspaceControl")
cmds.deleteUI(self.CONTROL_NAME + "WorkspaceControl")
log.debug("Removed", self.CONTROL_NAME + "WorkspaceControl")
else:
if cmds.window(self.CONTROL_NAME + "DockControl", ex=True):
log.debug("Removing", self.CONTROL_NAME + "DockControl")
cmds.deleteUI(self.CONTROL_NAME + "DockControl")
log.debug("Removed", self.CONTROL_NAME + "DockControl")
self.setAttribute(Qt.WA_DeleteOnClose, True)
# Set object name and window title
self.setObjectName(self.CONTROL_NAME)
self.setWindowTitle(self.DOCK_LABEL_NAME)
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.main_layout = QVBoxLayout()
self.central_widget.setLayout(self.main_layout)
self.build_ui()
@staticmethod
def delete_instances():
for ins in BroMainWindow_Dockable.instances:
try:
log.debug('Delete {}'.format(ins))
except:
log.debug('Window reference seems to be removed already, ignore.')
try:
ins.setParent(None)
ins.deleteLater()
except:
# ignore the fact that the actual parent has already been deleted by Maya...
pass
try:
BroMainWindow_Dockable.instances.remove(ins)
del ins
except:
# Supress error
pass
def build_ui(self):
"""
This function is called at the end of window initialization and creates your actual UI.
Override it with your UI.
"""
pass
# ----------------------------------------------------------------------------------------------------------------------
# Functions
# ----------------------------------------------------------------------------------------------------------------------
def getMainWindow():
"""
Get main Maya window instance.
"""
mayaMainWindowPtr = omui.MQtUtil.mainWindow()
mayaMainWindow = wrapInstance(long(mayaMainWindowPtr), QMainWindow)
return mayaMainWindow
def dock_window(dialog_class, width=440):
"""
This function is to be updates to actually dock window on creation to the right.
"""
dock_win = dialog_class()
dock_win.show(dockable=True)
return dock_win
def show_test():
# This is how to call and show a window
ChildTestWindow().show(dockable=True)
# ----------------------------------------------------------------------------------------------------------------------
# Example class
# ----------------------------------------------------------------------------------------------------------------------
class ChildTestWindow(BroMainWindow_Dockable):
"""
Example child window inheriting from main class.
"""
DOCK_LABEL_NAME = 'child test window' # Window display name
instances = list()
CONTROL_NAME = 'child_test_win' # Window unique object name
def __init__(self):
super(ChildTestWindow, self).__init__()
def build_ui(self):
self.my_label = QLabel('Beam me up, Scotty!')
self.main_layout.addWidget(self.my_label)
self.menuBar = QMenuBar()
self.presetsMenu = self.menuBar.addMenu(("&Presets"))
self.saveConfigAction = QAction(("&Save Settings"), self)
self.presetsMenu.addAction(self.saveConfigAction)
self.setMenuBar(self.menuBar)
self.statusBar = QStatusBar()
self.statusBar.showMessage("Status bar ready.")
self.setStatusBar(self.statusBar)
self.statusBar.setObjectName("statusBar")
self.setStyleSheet("#statusBar {background-color:#faa300;color:#fff}")
@LucyDimitri
Copy link

Hi,
Thanks for your script !!
Can you help me modify the code to load a Ui file rather than create the interface directly in build_ui ?
Or maybe I can convert my Ui to Py and load it ?

For now, I can't do it

thank you,

@Nixellion
Copy link
Author

Hi,
Thanks for your script !!
Can you help me modify the code to load a Ui file rather than create the interface directly in build_ui ?
Or maybe I can convert my Ui to Py and load it ?

For now, I can't do it

thank you,

Hi,

Would this help, maybe?
https://gist.github.com/fredrikaverpil/a70f38c8b04c49aaf73c1d22846f924a

You should be able to just load your UI inside the build_ui function. You may need to remove the lines


        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        self.main_layout = QVBoxLayout()
        self.central_widget.setLayout(self.main_layout)

I don't think they are needed if you load your ui from file.

@lalamax3d
Copy link

from where i can find BroTools repo.? is it private.? and not meant by public.?

@Nixellion
Copy link
Author

from where i can find BroTools repo.? is it private.? and not meant by public.?

Hi, yes, BroTools is a commercial product and repo is not public.

@lalamax3d
Copy link

thanks:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment