PyQt and Maya's scriptedPanels

338 views
Skip to first unread message

dgovil

unread,
Apr 4, 2012, 8:32:48 PM4/4/12
to python_inside_maya
Hey guys,
I want to create a few PyQt UI's to keep all my animation tools in a
particular area and cut down on clutter.
I know this must be possible because I've seen a few GUI's pull it off
like this: http://www.martintomoya.com/Site/tools_info.html

Specifically I would like to embed the channel box into a PyQt UI, and
I've read the way to do it is with scriptedPanels but I can't figure
out how to implement this in PyQT.
http://download.autodesk.com/global/docs/maya2012/en_us/CommandsPython/scriptedPanel.html

THe first problem is that according to the docs, this is pretty much a
MEL only function as far as I can tell.
The other is, I'd rather stick to Python if possible than MEL.

I'm wide open to ideas. Much appreciated.

-Dhruv

Jo Jürgens

unread,
Apr 11, 2012, 6:02:51 PM4/11/12
to python_in...@googlegroups.com
Nathan Horne has several very useful posts about PyQt and Maya. You should read this:  http://nathanhorne.com/?p=381 

Using the code in that post, here's how to achieve what you want:

import pymel.all as p

class MayaSubWindow(QtGui.QMainWindow):
    def __init__(self, parent=getMayaWindow()):
        super(MayaSubWindow, self).__init__(parent)
        self.centralwidget = QtGui.QWidget(self)
        self.layout = QtGui.QVBoxLayout(self.centralwidget)

        self.box = p.channelBox('myHappyBox')

        # add the standard right click menu. Doesnt work too well - 
        # most operations use the default channelBox no matter what
        self.popup = p.popupMenu()
        p.popupMenu(self.popup, e=True, postMenuCommand=lambda *x: p.mel.generateChannelMenu(self.popup, True))
        qtObj = toQtObject(self.box)
        self.layout.addWidget(qtObj)
        self.setCentralWidget(self.centralwidget)


myWindow = MayaSubWindow()
myWindow.show()

Use this if the code is garbled in this mail:



dgovil

unread,
Apr 13, 2012, 1:12:38 AM4/13/12
to python_inside_maya
Thanks! That's a good starting base and I should be able to figure it
out from hereon in. Cheers!
> >http://download.autodesk.com/global/docs/maya2012/en_us/CommandsPytho...

Richard Kazuo

unread,
Apr 17, 2012, 5:27:22 PM4/17/12
to python_in...@googlegroups.com
Thanks for this nice piece of code!

Strangely right-mouse clicks aren't working here... (Maya 2011 x64)

# MelError: Error during execution of MEL script: generateChannelMenu("MayaWindow|MainAttributeEditorLayout|formLayout37|AEmenuBarLayout|myHappyBox|popupMenu79",True);

# Line 1.116: Invalid use of Maya object "True".


Anyone can confirm if you can right-click the new channelbox and open the popup-menu?



2012/4/11 Jo Jürgens <joju...@gmail.com>

Justin Israel

unread,
Apr 17, 2012, 6:03:16 PM4/17/12
to python_in...@googlegroups.com
Seems like pymel's eval functionality isn't converting your bool True -> 1

Maybe try this:
    p.mel.generateChannelMenu(self.popup, 1)

Or just use the standard mel module:

import cmds.mel as mm
mm.eval('generateChannelMenu("%s", 1)' % self.popup)

Justin Israel

unread,
Apr 17, 2012, 6:04:17 PM4/17/12
to python_in...@googlegroups.com
Sorry, typo:

import maya.mel as mm
mm.eval('generateChannelMenu("%s", 1)' % self.popup)

Chad Dombrova

unread,
Apr 17, 2012, 6:09:21 PM4/17/12
to python_in...@googlegroups.com
yeah, i remember this bug. it's fixed if you install the latest pymel or use maya > 2011.

-chad

Richard Kazuo

unread,
Apr 17, 2012, 7:11:16 PM4/17/12
to python_in...@googlegroups.com
Justin's solution to change True to 1 works. :)
We're using Maya 2011  here at work so this will do for now.

Thanks guys!

Jo Jürgens

unread,
Apr 18, 2012, 10:24:23 AM4/18/12
to python_in...@googlegroups.com
I played around with this a bit. Here's how to add a PyQt menu to Maya, so you can have icons in Maya menus (you loose optionBoxes though)



import os

from PyQt4 import QtCore as QtCore

from PyQt4 import QtGui as QtGui

import sip

import pymel.all as p

import maya.OpenMayaUI as apiUI


class MayaQtMenu(QtGui.QWidget):

'''Show qTools menu (with icons) inside Maya'''

def __init__(self, name, label='', parent=None, lazy=False):

parent = parent or self.getMayaWindow()

QtGui.QWidget.__init__(self, parent)


label = label or name

self.name = name.replace(' ', '_')


if p.menu(self.name, exists=True):

p.menu(self.name, e=True, dai=True)

else:

p.menu(self.name, l=label, parent='MayaWindow')


self.menu = self.toQtObject(self.name)


if not lazy:

self.addItems()


def addItems(self):

'''Add menu items (actions) to menu. Placeholder. Must be implemented by subclass'''

pass


def getMayaWindow(self):

ptr = apiUI.MQtUtil.mainWindow()

return sip.wrapinstance(long(ptr), QtCore.QObject)


def toQtObject(self, mayaName):

'''

Given the name of a Maya UI element of any type,

return the corresponding QWidget or QAction.

If the object does not exist, returns None

'''

ptr = apiUI.MQtUtil.findControl(mayaName)

if ptr is None:

ptr = apiUI.MQtUtil.findLayout(mayaName)

if ptr is None:

ptr = apiUI.MQtUtil.findMenuItem(mayaName)

if ptr is not None:

return sip.wrapinstance(long(ptr), QtCore.QObject)



class qtIconsMenu(MayaQtMenu):


def addItems(self):

iconPath = p.util.getEnv('MAYA_LOCATION') + '/icons/'

pngs = [iconPath + f for f in os.listdir(iconPath) if '.png' in f]

by_letter = {}

for f in pngs:

prefix = os.path.basename(f).replace('icons','').replace('icons','')[0]

by_letter.setdefault(prefix, [])

by_letter[prefix].append(f)


for prefix, icons in by_letter.items():

submenu = QtGui.QMenu(self.menu)

submenu.setTearOffEnabled(True)

submenu.setTitle(prefix)

self.menu.addAction(submenu.menuAction())


def printPath(path):

print path


for iconPath in icons:

icon = QtGui.QIcon()

icon.addPixmap(QtGui.QPixmap(iconPath),

  QtGui.QIcon.Normal, QtGui.QIcon.Off)


menuItem = QtGui.QAction(self)

menuItem.setIcon(icon)

menuItem.setText(os.path.basename(iconPath))

menuItem.triggered.connect(lambda x, f=iconPath: printPath(f))

submenu.addAction(menuItem)


if __name__=='__main__':

qtIconsMenu('Maya Icons')

dgovil

unread,
Apr 18, 2012, 3:50:44 PM4/18/12
to python_inside_maya
Wow, thanks for all the info and code examples guys.
I'm going to try and cobble things together as soon as work lets up,
but all the stuff here should make for pretty smooth sailing.


Cheers
Reply all
Reply to author
Forward
0 new messages