-
-
Save liorbenhorin/69da10ec6f22c6d7b92deefdb4a4f475 to your computer and use it in GitHub Desktop.
''' | |
Template class for docking a Qt widget to maya 2017+. | |
Author: Lior ben horin | |
12-1-2017 | |
''' | |
import weakref | |
import maya.cmds as cmds | |
import maya.OpenMayaUI as omui | |
from shiboken2 import wrapInstance | |
from Qt import QtGui, QtWidgets, QtCore # https://github.com/mottosso/Qt.py by Marcus Ottosson | |
def dock_window(dialog_class): | |
try: | |
cmds.deleteUI(dialog_class.CONTROL_NAME) | |
logger.info('removed workspace {}'.format(dialog_class.CONTROL_NAME)) | |
except: | |
pass | |
# building the workspace control with maya.cmds | |
main_control = cmds.workspaceControl(dialog_class.CONTROL_NAME, ttc=["AttributeEditor", -1],iw=300, mw=True, wp='preferred', label = dialog_class.DOCK_LABEL_NAME) | |
# now lets get a C++ pointer to it using OpenMaya | |
control_widget = omui.MQtUtil.findControl(dialog_class.CONTROL_NAME) | |
# conver the C++ pointer to Qt object we can use | |
control_wrap = wrapInstance(long(control_widget), QtWidgets.QWidget) | |
# control_wrap is the widget of the docking window and now we can start working with it: | |
control_wrap.setAttribute(QtCore.Qt.WA_DeleteOnClose) | |
win = dialog_class(control_wrap) | |
# after maya is ready we should restore the window since it may not be visible | |
cmds.evalDeferred(lambda *args: cmds.workspaceControl(main_control, e=True, rs=True)) | |
# will return the class of the dock content. | |
return win.run() | |
class MyDockingUI(QtWidgets.QWidget): | |
instances = list() | |
CONTROL_NAME = 'my_workspcae_control' | |
DOCK_LABEL_NAME = 'my workspcae control' | |
def __init__(self, parent=None): | |
super(MyDockingUI, self).__init__(parent) | |
# let's keep track of our docks so we only have one at a time. | |
MyDockingUI.delete_instances() | |
self.__class__.instances.append(weakref.proxy(self)) | |
self.window_name = self.CONTROL_NAME | |
self.ui = parent | |
self.main_layout = parent.layout() | |
self.main_layout.setContentsMargins(2, 2, 2, 2) | |
# here we can start coding our UI | |
self.my_label = QtWidgets.QLabel('hello world!') | |
self.main_layout.addWidget(self.my_label) | |
@staticmethod | |
def delete_instances(): | |
for ins in MyDockingUI.instances: | |
logger.info('Delete {}'.format(ins)) | |
try: | |
ins.setParent(None) | |
ins.deleteLater() | |
except: | |
# ignore the fact that the actual parent has already been deleted by Maya... | |
pass | |
MyDockingUI.instances.remove(ins) | |
del ins | |
def run(self): | |
return self | |
# this is where we call the window | |
my_dock = dock_window(MyDockingUI) |
Sachtein
Hi, @liorbenhorinliorbenhorin !
This is great boilerplate. I succesfully repurposed it as a base module and class, which I can use in different windows. Tested in Maya 2017, worked great. I will be performing tests of it in different Maya versions.
But I'm writing because of a small problem I found. It seems that this window does not show the menuBar, when I use self.setMenuBar(manuBarVar)
command. Is there a solution to this?
Thanks.
Hi all this is a good stuff but I have a problem. The dock windows can show only one time , if I run the code it delete instance and cannot pop up again.
Any solutions please?
Thanks
where do you set self.setSizeGripEnabled(False)? This new way won't let me set those attributes to my window anymore
I test this version. And which more better. Right now I need to configure my old window setup.
Thank you for this.
Hi,
Thanks for your script !!
Can you help me modify the code to load a Ui file rather than create the interface directly in this code?
Or maybe I can convert my Ui to Py and load it ?
thank you,
Hi,
Thanks for your script !!
Can you help me modify the code to load a Ui file rather than create the interface directly in this code?
Or maybe I can convert my Ui to Py and load it ?thank you,
It should be straightforward in python, see loadUi
You could also take a look at the previous version of this script. It loaded and parsed .ui
files here
Hi,
Thanks for your script !!
Can you help me modify the code to load a Ui file rather than create the interface directly in this code?
Or maybe I can convert my Ui to Py and load it ?thank you,
If you want to convert *.ui file. You need to use pyuic in console/terminal.
There's 2 type of python bind as I remembered, PyQt and PySide
Maya used PySide2. So in your folder that contain *.ui file right click and use "cmd here"
or..
Open cmd/terminal change directory to your folder then type some command
or...
You can type cmd in folder direction, press enter then type:
#for PyQt5, use:
pyuic5 -x yourUiFilename.ui -o yourUiFileConvertName.py
#if you want to use PySide2:
pyside2-uic -x yourUiFilename.ui -o yourUiFileConvertName.py
So if there's no error in your command you will see *.py extension file inside your folder.
If you don't want to confused yourself to pure PyQt/PySide ui build and just want to build from existing *.ui file and focus on tool development try this https://github.com/prsfx/MayaDockTool
I believed this method way more faster to develope tool. Build HUGE interface is pain in the ass.
If you still confused, I don't know what you want to do with your tool.
Good luck.
This is good stuff. I'm trying to use this to build a base class that has a docking method so I can inherit in other UI classes. It mostly works, except the main_layout doesn't display. I will post more if I get a solution.