Access Maya UI in Qt way using Python API

3,144 views
Skip to first unread message

Ruchit Bhatt

unread,
Sep 6, 2017, 6:18:18 AM9/6/17
to Python Programming for Autodesk Maya
Hi,
can i get example code to add / Modify / Remove Maya UI element in Qt way using python API ?

For example
1) set position of selected node in nodeEditor    (https://www.youtube.com/watch?v=pPfCM1T9IHM)
2) Attribute control      (https://vimeo.com/161801793)

Thank you

Simon Anderson

unread,
Sep 6, 2017, 6:41:37 AM9/6/17
to Python Programming for Autodesk Maya

Hi Ruchit,

I am not sure exactly what you are asking for. Do you want to create a Qt UI that performs some maya command. Here is a small snippet that creates a label and a small window.

Everything you see in the videos is all custom layouts built in Qt.

from maya import OpenMayaUI as omui
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from shiboken2 import wrapInstance  # << TODO: READ UP ABOUT

mayaMainWindowPtr = omui.MQtUtil.mainWindow()
mayaWindow = wrapInstance(long(mayaMainWindowPtr), QWidget)

hello = QLabel("test", parent=mayaWindow)
hello.setObjectName("test")
hello.setWindowFlags(Qt.Window) # makes the widget a standalone window even though it is parented
hello.show()


Here is some old code that creates a button adds it to a layout. you will have to add or set the layout for the active QWidget/QWindow
btn = QtGui.QButton("Button Name")
layout = QHBoxLayout()
layout.addWidget(btn)

To make the button execute some maya code:
btn.clicked.connect(clickedButton)

def clickedButton():
    # Maya code here

I hope that makes some sense. Qt is an extremely large API and you can make it do a ton of things, best would be to get a widget to appear and a button, and make the button perform something, and build on it from there.


Once you have got a widget displaying, look at the Qt help docs to start adding more widgets and customisations: http://doc.qt.io/qt-5/qtgui-module.html

I hope that helps,
Cheers

Cesar Saez

unread,
Sep 6, 2017, 8:29:30 AM9/6/17
to python_in...@googlegroups.com
Just a small note on Simon comments: please do not use import * (aka from x import *) it pollutes the name space with all sorts of things and the risk of name collisions/shadowing is very high. Also it's recommended to only import modules (same logic).

Other than that, his advice is spot on!
Cheers

Simon Anderson

unread,
Sep 6, 2017, 7:13:02 PM9/6/17
to Python Programming for Autodesk Maya
Totally agree with Cesar

Ruchit Bhatt

unread,
Sep 6, 2017, 11:42:23 PM9/6/17
to Python Programming for Autodesk Maya
@Simon
I know how PyQt/Pyside works, What i want to know is "How to modify pre-exist Maya UI element ?".

for instance
*Add custom action in QMenu of nodeEditor, GraphEditor,etc.
*Trigger QDialog on middle click to any node inside node editor.
*Set X & Y position of selected node inside node editor.
*Custom drop down menu in shelf.
*Modify font style in outliner.

using wrapInstance can i do this ??

Ruchit Bhatt

unread,
Sep 7, 2017, 1:29:52 AM9/7/17
to Python Programming for Autodesk Maya
See this basic test

import maya.cmds as mc
import maya.mel as mm
import maya.OpenMayaUI as omUI
from PySide import QtGui, QtCore
from shiboken import wrapInstance

mm
.eval('GraphEditor')


def getGraphEdtr():
    graphEdtrPtr
= omUI.MQtUtil.findLayout("graphEditor1Window|TearOffPane|graphEditor1")
   
return wrapInstance(long(graphEdtrPtr), QtGui.QWidget)
   
graphEdtr
= getGraphEdtr()
graphEdtr
.setWindowOpacity(0.4)


No idea why its not working

Cesar Saez

unread,
Sep 7, 2017, 5:15:47 AM9/7/17
to python_in...@googlegroups.com
In that snippet findLayout is returning the memory address of a layout with certain objectName (this is on the cpp side,  maya is a qt application so all widgets have an objectName). Wrapinstance basically cast/wrap whatever is in that memory address into the python class you pass in (they have to match!), returning an instance that you can modify using the api as usual (we are at the python side now).

Hope it makes sense, 
Cheers

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/ccf3f5ba-c641-485a-8aa3-65a9a6a7a3d3%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Cesar Saez

unread,
Sep 7, 2017, 5:20:31 AM9/7/17
to python_in...@googlegroups.com
Reading again, I guess it doesn't work because you are wrapping a layout (assuming there's an instance matching that name on the session) into a qwidget, I would try casting on a matching class so the bindings can do their job mapping the python calls to the cpp equivalent (same internal structure).

On Sep 7, 2017 7:15 PM, "Cesar Saez" <ces...@gmail.com> wrote:
In that snippet findLayout is returning the memory address of a layout with certain objectName (this is on the cpp side,  maya is a qt application so all widgets have an objectName). Wrapinstance basically cast/wrap whatever is in that memory address into the python class you pass in (they have to match!), returning an instance that you can modify using the api as usual (we are at the python side now).

Hope it makes sense, 
Cheers


On Sep 7, 2017 3:29 PM, "Ruchit Bhatt" <ruchitinn...@gmail.com> wrote:
See this basic test

import maya.cmds as mc
import maya.mel as mm
import maya.OpenMayaUI as omUI
from PySide import QtGui, QtCore
from shiboken import wrapInstance

mm
.eval('GraphEditor')


def getGraphEdtr():
    graphEdtrPtr
= omUI.MQtUtil.findLayout("graphEditor1Window|TearOffPane|graphEditor1")
   
return wrapInstance(long(graphEdtrPtr), QtGui.QWidget)
   
graphEdtr
= getGraphEdtr()
graphEdtr
.setWindowOpacity(0.4)


No idea why its not working

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsubscribe@googlegroups.com.

Mahendra Gangaiwar

unread,
Sep 8, 2017, 1:17:09 PM9/8/17
to python_in...@googlegroups.com

I think what you are looking for is:

QtWidgets.QApplication.allWidgets()
QtWidgets.QApplication.allWindows()
Or
QtWidgets.QApplication.activrWindow()

mm.eval('GraphEditor')
Ge = QtWidgets.QApplication.activrWindow()
print Ge.windowTitle()
Ge.setWindowOpacity(0.5)

-M


On Thu 7 Sep, 2017, 2:50 PM Cesar Saez <ces...@gmail.com> wrote:
Reading again, I guess it doesn't work because you are wrapping a layout (assuming there's an instance matching that name on the session) into a qwidget, I would try casting on a matching class so the bindings can do their job mapping the python calls to the cpp equivalent (same internal structure).
On Sep 7, 2017 7:15 PM, "Cesar Saez" <ces...@gmail.com> wrote:
In that snippet findLayout is returning the memory address of a layout with certain objectName (this is on the cpp side,  maya is a qt application so all widgets have an objectName). Wrapinstance basically cast/wrap whatever is in that memory address into the python class you pass in (they have to match!), returning an instance that you can modify using the api as usual (we are at the python side now).

Hope it makes sense, 
Cheers


On Sep 7, 2017 3:29 PM, "Ruchit Bhatt" <ruchitinn...@gmail.com> wrote:
See this basic test

import maya.cmds as mc
import maya.mel as mm
import maya.OpenMayaUI as omUI
from PySide import QtGui, QtCore
from shiboken import wrapInstance

mm
.eval('GraphEditor')


def getGraphEdtr():
    graphEdtrPtr
= omUI.MQtUtil.findLayout("graphEditor1Window|TearOffPane|graphEditor1")
   
return wrapInstance(long(graphEdtrPtr), QtGui.QWidget)
   
graphEdtr
= getGraphEdtr()
graphEdtr
.setWindowOpacity(0.4)


No idea why its not working

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAPamJi82Ce5rjZkz6LVdRvBwD%2BBs0zAbJH-DA1TTWYMqpoF7jg%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.
--
Best,

-M

Ruchit Bhatt

unread,
Sep 9, 2017, 7:46:06 AM9/9/17
to Python Programming for Autodesk Maya
@Mahendra Gangaiwar
Thnx
dict((w.objectName(), w) for w in QtWidgets.QApplication.allWidgets())
dict
((w.objectName(), w) for w in QtWidgets.QApplication.allWindows())


is super useful to get objectName of all instance.But


mm.eval('GraphEditor')
 
Ge = QtWidgets.QApplication.activeWindow()
 
print Ge.windowTitle()
 
Ge.setWindowOpacity(0.5)


This is still not working  (print Ge.windowTitle()   #Result Script Editor)




Let's take one more example, in ReferenceEditor if i want to select item02(i.e Test03RN Test03.ma) & item03(i.e Test04RN Test04.ma)  inside refEdEditorPane. How can i do that via PySide  ??


Before





















After

kevco...@gmail.com

unread,
Sep 11, 2017, 3:05:43 PM9/11/17
to Python Programming for Autodesk Maya
I'm guessing you're running the above code in the script editor? which makes sense for it printing 'Script Editor' since that is the active window.

You're going to need to explore the widget hierarchy a bit to trickle down to the widgets you're wanting to do things to.

there is an example script in the maya examples that creates a treeview of children for the maya main window. that would be a good place to start on figuring out how to do that.

Ruchit Bhatt

unread,
Sep 12, 2017, 12:37:24 AM9/12/17
to Python Programming for Autodesk Maya
@kevin Cortez........WidgetHierarchyTree is awesome, Thnx much for info. Will try to hack more.


Alok Gandhi

unread,
Sep 12, 2017, 9:38:29 AM9/12/17
to python_in...@googlegroups.com
Great! Also in the same folder of examples, you will find a script editMayaWidgets.py that does exactly what you need.

Btw, all of these can also be found on github (maya 2016 only), Maya 2017 is available as a free download on Autodesk AppExchange

Cheers!

- Alok

On Tue, Sep 12, 2017 at 12:37 PM, Ruchit Bhatt <ruchitinn...@gmail.com> wrote:
@kevin Cortez........WidgetHierarchyTree is awesome, Thnx much for info. Will try to hack more.


--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/5b191296-a7e9-4768-86fb-9e8013861834%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--

Ruchit Bhatt

unread,
Sep 22, 2017, 1:11:04 AM9/22/17
to Python Programming for Autodesk Maya
@Alok Gandhi

I tried that example (working fine), And based on that i also tried below lines








This one also working fine, but tell me one thing. Why sceneEditor widget is missing under list of "referenceEditorPanel1referenceEditorPanel" children ??

how to query that list ??

Ruchit Bhatt

unread,
Sep 25, 2017, 11:39:32 AM9/25/17
to Python Programming for Autodesk Maya
First hack with node editor

See this
Maya Align Nodes (PySide)
Reply all
Reply to author
Forward
0 new messages