A question came up in the Maya-Python mailing list that I thought was a really good topic, and should be reposted.

Someone asked how you can create maya UI objects and embed them within your main PyQt application. Specifically he wanted to create a modelPanel and embed it so that he would have a camera view within his own PyQt window.

Here is my example of how to achieve this…

from PyQt4 import QtCore, QtGui

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

import sip

global app


class MyDialog(QtGui.QDialog):

    def __init__(self, parent, **kwargs):
        super(MyDialog, self).__init__(parent, **kwargs)
        
        self.setObjectName("MyWindow")
        self.resize(800, 600)
        self.setWindowTitle("PyQt ModelPanel Test")

        self.verticalLayout = QtGui.QVBoxLayout(self)
        # need to set a name so it can be referenced by maya node path
        self.verticalLayout.setObjectName("mainLayout")
        # First use SIP to unwrap the layout into a pointer
        # Then get the full path to the UI in maya as a string
        layout = mui.MQtUtil.fullName(long(sip.unwrapinstance(self.verticalLayout)))
        cmds.setParent(layout)

        self._cameraName = cmds.camera()[0]
        nodeName = cmds.modelPanel(cam=self._cameraName)
        # Find a pointer to the modelPanel that we just created
        ptr = mui.MQtUtil.findControl(nodeName)
        # Wrap the pointer into a python QObject
        self.modelPanel = sip.wrapinstance(long(ptr), QtCore.QObject)

        # add our QObject reference to the modelPanel to our layout
        self.verticalLayout.addWidget(self.modelPanel)

    def show(self):
        super(MyDialog, self).show()
        # maya can lag in how it repaints UI. Force it to repaint
        # when we show the window.
        self.modelPanel.repaint()
                    

def show():
    global app
    # use a shared instance of QApplication
    app = QtGui.QApplication.instance()

    # get a pointer to the maya main window
    ptr = mui.MQtUtil.mainWindow()
    # use sip to wrap the pointer into a QObject
    win = sip.wrapinstance(long(ptr), QtCore.QObject)
    d = MyDialog(win)
    d.show()

    return d

You need sip and the MQtUtil functions to convert between maya node paths and python Qbjects. Its the same idea as having to use those functions to get a reference to the maya MainWindow, in order to parent your dialog.

  4 Responses to “Mixing PyQt4 widgets and Maya UI objects”

  1. As you described, I could ship a camera on PyQT UI.
    But, I want to do something more.
    I tried add pushbutton on camera view(a.k.a modelPanel) with addWidget method. However, it didn’t work well.
    I dreamed the camera view that could be controlled freely and have attached HUD items.
    Is there any way to solve my problem?

  2. @ica – If you are trying to overlay widgets on top of the camera view to simulate a HUD, then you would probably not want to add the PushButton to the Vertical Layout. That would just end up putting it underneath as it is laying widgets out in a column. What you probably just want to do is create the button and parent it to the Model Panel, but don’t add it to a layout. Then you can Move it to the location you want and it will sit freely on top of your camera view. I haven’t tested this but its my best guess :-)

  3. Sorry for late feedback.
    As you recommened, I tried “JUST” parent the QPushButton to Model Panel. Actually, I parented one of Model Panel’s children. It doesn’t mess up the camera view, and it can move on the view as I command.
    But, when I add a QPushButton once again, something happens. At the time additional creation, position is reset! I means that everytime I add buttons on Model Panel, I have to re-position all of the buttons. How can I lock them all?

    • Im not exactly sure what happening. Can you email me directly and we can look at some of your code samples? As a workaround for now, you COULD just create a convenience method for adding a new button that adds it and repositions all the existing buttons again. Probably could save button positions to a dictionary each time and then use that for realigning them. It could be Maya’s parent widgets not liking free floating children not in layouts..Who knows. Ideally they should stay put.

 Leave a Reply

(required)

(required)


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
© 2011 Justin Israel | justinfx.comSuffusion theme by Sayontan Sinha