2010
04.21

PyQt and Maya 2011

Re-posting some information here that I had posted on TD club:

import maya.OpenMayaUI as mui
import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
import sip

def getMayaWindow():
    #Get the maya main window as a QMainWindow instance
    ptr = mui.MQtUtil.mainWindow()
    return sip.wrapinstance(long(ptr), QtCore.QObject)

class MayaSubWindow(QtGui.QMainWindow):
    'My custom window, which i want to parent to the maya main window'
    def __init__(self, parent=getMayaWindow()):
        #Init my main window, and pass in the maya main window as it's parent
        QtGui.QMainWindow.__init__(self, parent)

#Show my window
myWindow = MayaSubWindow()
myWindow.show()

Here’s a quick little bit of code showing how to create a custom GUI class using pyqt (Almost all the pyqt examples use this over using some form of .ui file, because it allows for much more control). You can also use it in combination with ui files thanks to pyqt’s uic module.

QT does not require objects to have “names”, but if you ever want to find your pyqt objects using MQtUil.findControl then you need to assign it a name using OBJECT.setObjectName(“AwesomeWindow”). In the above example, in the MayaSubWindow.__init__ function you would call self.setObjectName(“AwesomeWindow”).

Also, since qt does not require names, it also does not require that control names be unique, so it’s completely possible to use findControl and get the “wrong” object. So you may want to ensure that the name you are using is unique if you want to use it to find that object again later. (Also, you can skip the whole findControl step by just using instance variables to keep track of all your controls, like what the pyqt examples use)

Here’s a pyqt example using uic to load in a ui file (Rather than maya’s new loadUi command, which wont give you all your pyqt objects.

import os
import sip

import maya.cmds as cmds
import maya.OpenMayaUI as mui

from PyQt4 import QtGui, QtCore, uic

def getMayaWindow():
	'Get the maya main window as a QMainWindow instance'
	ptr = mui.MQtUtil.mainWindow()
	return sip.wrapinstance(long(ptr), QtCore.QObject)

#Get the absolute path to my ui file
uiFile = os.path.join(cmds.internalVar(upd=True), 'ui', 'demo.ui')
print 'Loading ui file:', os.path.normpath(uiFile)

#Load the ui file, and create my class
form_class, base_class = uic.loadUiType(uiFile)
class Window(base_class, form_class):
	def __init__(self, parent=getMayaWindow()):
		'''A custom window with a demo set of ui widgets'''
		#init our ui using the MayaWindow as parent
		super(base_class, self).__init__(parent)
		#uic adds a function to our class called setupUi, calling this creates all the widgets from the .ui file
		self.setupUi(self)
		self.setObjectName('myWindow')
		self.setWindowTitle("My Qt Demo Window")

def main():
	global myWindow
	myWindow = Window()
	myWindow.show()

Designer .UI file

The python code will look for the ui file in maya2011\prefs\ui\demo.ui. It will print a message with the absolute path when running.
  1. This is great, but I can’t for the life of me figure out how to load a UI file’s QMenu directly into the Maya menu bar. Any ideas?

    I have a stripped down UI file that only contains QMainWindow >> QMenuBar and various QMenus with their associated QActions. No buttons or anything like that—just menu stuff.

    At the end of the day I’m trying to have myself a UIMenu and UIDocker class that handle all the UI file initialization on the fly. That way, I can create a series of dockers and menus for Maya with ease, never having to deal with the code you have above more than once.

    That’s the idea, anyway. I got my dockers working fine, but the menus are proving to be difficult!

  2. Nathan, this is great reference, it’s been very helpful and fast to be able to get Designer .ui files in Maya 2012. I really appreciate the help. I have a question though, how would you use a second .ui file as a second window which pops up from a button on the first window?

  3. …nevermind Nathan, I was able to figure this out once I understood that uic.loadtype() was generating the two necessary classes for inheritance into my UI class. I’m new to writing classes and using class inheritence. Thanks for you time, and thanks for the code reference.

  4. Never mind my previous comment… I downloaded the latest version of PyQt x64 for Python 2.6 and it worked. Something very strange was happening before that!

  5. I was working on some Maya tools for our studio and found this to be an excellent starting point for using PyQt with Maya.

    I was wondering if you had a reliable and simple method to make sure that only one copy of your window is open at once? We use the shelf to launch scripts and usually in the script we will check if the window exists, close it if it does, and then load the UI. It would be great to be able to duplicate this functionality with PyQt interfaces, but I can’t seem to find a good way to do it.

    Any help would be greatly appreciated!

  6. I always create a simple main() or showUi() function that stores the window into a variable. Before creating a new instance first try to close the previous one.
    EX:

    def main():
    global win
    try:
    win.close()
    except: pass
    win = MyWindowClass()
    win.show()

You must be logged in to post a comment.