How to embed modelPanel to a pyqt ui (again) ?

944 views
Skip to first unread message

oglop

unread,
May 23, 2014, 1:50:56 PM5/23/14
to python_in...@googlegroups.com
i know this has been asked on 2011 and Justine has an awesome example here
you saw the last few lines i commented out the setObjectName xxxx and yyyyy, without them, when you run the code in maya, it successfully opens the ui, but when you press 4 or 5 on the modelPanel, you will see the following error message similar to :

updateModelPanelBar MayaWindow|||formLayout1|viewPanes|modelPanel4|modelPanel5|modelPanel5;

notice the ||| part.

it seems as if without object names set, maya doesn't know how to find the newly created modelPanel. also if i'm using mainwindow i also see this error unless i set object names using an awkward workaround.

example1

from PyQt4 import QtCore,QtGui

import maya.cmds as cmds
import maya.OpenMayaUI as OpenMayaUI
import sip

def getMayaWindow():
    windowPointer
= OpenMayaUI.MQtUtil.mainWindow()
   
return sip.wrapinstance(long(windowPointer), QtCore.QObject)

class MayaView(QtGui.QDialog):
   
def __init__(self,parent=None,**kwargs):
       
super(MayaView,self).__init__(parent,**kwargs)
       
       
self.setObjectName('MyWindow')
       
       
self.setWindowTitle('3dView')
       
       
self.verticalLayout = QtGui.QVBoxLayout(self)
       
self.verticalLayout.setContentsMargins(0,0,0,0)
       
self.verticalLayout.setObjectName("mainLayout")
       
        applyBut
= QtGui.QPushButton('Apply')
        closeBut
= QtGui.QPushButton('Close')
        butLayout
= QtGui.QHBoxLayout()
        butLayout
.addWidget(applyBut)
        butLayout
.addWidget(closeBut)
        butLayout
.setObjectName("xxxBut")
           
        layout
= OpenMayaUI.MQtUtil.fullName(long(sip.unwrapinstance(self.verticalLayout)))
       
print "vertical layout",layout
       
        cmds
.setParent(layout)
       
        paneLayoutName
= cmds.paneLayout()    
       
# find a pointer to the paneLayout that we just created
        ptr
= OpenMayaUI.MQtUtil.findControl(paneLayoutName)
       
# warp the pointer into a python QObject
       
self.paneLayout = sip.wrapinstance(long(ptr),QtCore.QObject)  
           
       
# new create a camera
       
self.cameraName = cmds.camera(n='PickerView_camera')[0]
        cmds
.hide(self.cameraName)
        cmds
.viewFit(self.cameraName,all=True)
       
self.modelPanelName = cmds.modelPanel(cam=self.cameraName,parent=paneLayoutName)
       
       
# edit model panel
        modelEditorValue
= cmds.modelPanel(self.modelPanelName,q=True,me=True)
        cmds
.modelEditor(modelEditorValue,e=True,da='smoothShaded',ca=False,grid=False,hud=False,\
                         manipulators
=False,displayTextures=True,ha=False,j=False,ikh=False,df=False,\
                         dim
=False,lc=False,nc=True,wos=False,dl='default',av=False)
       
       
# find a pointer to the modelPanel that we just created        
        ptr
= OpenMayaUI.MQtUtil.findControl(self.modelPanelName)
       
#wrap the pointer into a python QObject
       
self.modelPanel = sip.wrapinstance(long(ptr),QtCore.QObject)
       
#add our QObject reference to the paneLayout to our layout
       
self.verticalLayout.addWidget(self.paneLayout)
       
self.verticalLayout.addLayout(butLayout)
       
self.verticalLayout.setSpacing(0)
       
self.setLayout(self.verticalLayout)
       
       
self.setFixedSize(400,600)
       
class MainWin(QtGui.QDialog):
   
def __init__(self,parent=getMayaWindow()):
       
super(MainWin,self).__init__(parent)
        cam
= MayaView()
       
# self.setObjectName('xxxxxx')
        but
= QtGui.QPushButton('zzz')
        layout
= QtGui.QVBoxLayout()
        layout
.addWidget(but)
        layout
.addWidget(cam)
       
self.setLayout(layout)    
       
# layout.setObjectName('yyyyy')
       
a
= MainWin()
a
.show()  





example2:

from PyQt4 import QtCore,QtGui

import maya.cmds as cmds
import maya.OpenMayaUI as OpenMayaUI
import sip
def getMayaWindow():
    windowPointer
= OpenMayaUI.MQtUtil.mainWindow()
   
return sip.wrapinstance(long(windowPointer), QtCore.QObject)
class MayaView(QtGui.QWidget):
   
def __init__(self,parent=None,**kwargs):
       
super(MayaView,self).__init__(parent,**kwargs)
       
       
self.setObjectName('MyWindow')
       
       
self.setWindowTitle('3dView')
       
       
self.verticalLayout = QtGui.QVBoxLayout(self)
       
self.verticalLayout.setContentsMargins(0,0,0,0)
       
self.verticalLayout.setObjectName("mainLayout")
       
       
        applyBut
= QtGui.QPushButton('Apply')
        closeBut
= QtGui.QPushButton('Close')
        butLayout
= QtGui.QHBoxLayout()
        butLayout
.addWidget(applyBut)
        butLayout
.addWidget(closeBut)
           
        layout
= OpenMayaUI.MQtUtil.fullName(long(sip.unwrapinstance(self.verticalLayout)))
        cmds
.setParent(layout)
       
        paneLayoutName
= cmds.paneLayout()    
       
# find a pointer to the paneLayout that we just created
        ptr
= OpenMayaUI.MQtUtil.findControl(paneLayoutName)
       
# warp the pointer into a python QObject
       
self.paneLayout = sip.wrapinstance(long(ptr),QtCore.QObject)  
           
       
# new create a camera
       
self.cameraName = cmds.camera(n='PickerView_camera')[0]
        cmds
.hide(self.cameraName)
        cmds
.viewFit(self.cameraName,all=True)
       
       
self.modelPanelName = cmds.modelPanel(cam=self.cameraName)
        cmds
.panel(self.modelPanelName,e=True,mbv=False)
        flayout
= cmds.modelPanel(self.modelPanelName,q=True,barLayout=True)
        cmds
.frameLayout(flayout,e=True,collapse=True)
       
# edit model panel
        modelEditorValue
= cmds.modelPanel(self.modelPanelName,q=True,me=True)
        cmds
.modelEditor(modelEditorValue,e=True,da='smoothShaded',ca=False,grid=False,hud=False,\
                         manipulators
=False,displayTextures=True,ha=False,j=False,ikh=False,df=False,\
                         dim
=False,lc=False,nc=True,wos=False,dl='default',av=False)
       
       
# find a pointer to the modelPanel that we just created        
        ptr
= OpenMayaUI.MQtUtil.findControl(self.modelPanelName)
       
#wrap the pointer into a python QObject
       
self.modelPanel = sip.wrapinstance(long(ptr),QtCore.QObject)
       
#add our QObject reference to the paneLayout to our layout
       
self.verticalLayout.addWidget(self.paneLayout)
       
self.verticalLayout.addLayout(butLayout)
       
self.verticalLayout.setSpacing(0)
       
self.setLayout(self.verticalLayout)
       
       
self.setFixedSize(400,600)
       
class MainWin(QtGui.QMainWindow):
   
def __init__(self,parent=getMayaWindow()):
       
super(MainWin,self).__init__(parent)
       
self.setObjectName('QtMainWindow')
       
self.mid = QtGui.QMdiArea()
       
self.mid.setObjectName('QMdiArea')
       
self.setCentralWidget(self.mid)
   
       
        cam
= MayaView()
       
       
self.mid.addSubWindow(cam)
a
= MainWin()
a
.show()    


Justin Israel

unread,
May 23, 2014, 3:23:47 PM5/23/14
to python_in...@googlegroups.com

Wasn't sure if this was a question or another example of how to do it?

Also another thing I found was that Maya didn't seem to like layouts being added to layouts. I had to add a widget in between. Maybe that has changed. Haven't tested it in the latest Maya.

- Justin (aka Justine)

--
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/34591c50-38dd-4155-977d-5422f0665649%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

oglop

unread,
May 24, 2014, 12:34:18 AM5/24/14
to python_in...@googlegroups.com
that was a question , because if i do a complex ui, there are many nested layout, and there will be ||| errors, when i press 4 or 5 ? shall i manually call setObjectName on all the "missing" layouts?  this doesn't feel correct to me .)

        ptr
<span style="co
...

Justin Israel

unread,
May 24, 2014, 12:52:23 AM5/24/14
to python_in...@googlegroups.com

I'm not sure if there really is a "correct" way to be doing this anyways, since it is the process of hijacking Maya's UI elements and interacting with how it has implemented it's translation between QWidgets and the Maya object path.

I would have to say that as far as I know, and have tested, setting object names on all of the parent elements of the intended Maya UI element is kind of necessary.

The whole thing is pretty much an unsupported trick.

--
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.

Marcus Ottosson

unread,
May 24, 2014, 5:40:12 AM5/24/14
to python_in...@googlegroups.com

shall i manually call setObjectName on all the “missing” layouts? this doesn’t feel correct to me .)

I might add that an object can only ever have 1 name. So if it turns out Maya is actually using the objectName that you are changing, you might end up breaking things; and there is no undo for that. :)

On the other hand, setting objectNames “manually” certainly isn’t “hacky” or even “manual”; Qt isn’t setting those names for you, they are meant to be set by you for you to distinguish them from other objects, however like I said, Maya may have already done that for a reason.




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



--
Marcus Ottosson
konstr...@gmail.com

nesto...@gmail.com

unread,
Sep 15, 2017, 4:11:19 PM9/15/17
to Python Programming for Autodesk Maya

hello, and by the way have you found a solution for the |||| in the name when is a nested layout working as a parent ??

AJ

unread,
Sep 26, 2017, 12:02:10 PM9/26/17
to Python Programming for Autodesk Maya
+1

Justin Israel

unread,
Sep 26, 2017, 2:23:32 PM9/26/17
to Python Programming for Autodesk Maya


On Sat, Sep 16, 2017, 8:11 AM <nesto...@gmail.com> wrote:

hello, and by the way have you found a solution for the  |||| in the name when is a nested layout working as a parent ??

As mentioned, you have to set object names for everything. And also avoid adding a layout to a layout. You should put widgets between layouts :

Widget - layout - widget - layout 


--
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.

nesto...@gmail.com

unread,
Sep 26, 2017, 2:51:48 PM9/26/17
to Python Programming for Autodesk Maya
Yes, after following many recomendations like yours, i found out that the sign " | " actually represent a layout without name in the route, so if you have something like G.Ex: my_window||||my_layout|etc|etc .. that means that you have 3 layouts without name, you have, why i said 3 and not 4 if there are 4 | between my_window and my_layout ? because we have to be aware that one of those " | " is the way how maya represents the hiererchy in paths, in my test, at least in mine, dont mind if we have nested layouts, or widgets in bettween, you just have to name all layouts that will represent the path to the viweport, not the widgets, in first i put a name on the widgets too, but just for testing after i deleted the object name from the widgets and leave it on the layouts and still work on ! thank you ! now everything will be ok !!
Message has been deleted

tim2018

unread,
Aug 17, 2018, 12:15:54 PM8/17/18
to Python Programming for Autodesk Maya
Hello, Thanks for the examples but I noticed that none of the icons in modelEditorIconBar seem to work. Clicking on shaded or wireframe icons have no effect in the viewport. Does anyone know how to fix this problem? I am referring to example1.

Thanks

Justin Israel

unread,
Aug 19, 2018, 9:37:42 PM8/19/18
to python_in...@googlegroups.com
On Sat, Aug 18, 2018 at 4:14 AM tim2018 <tk...@themill.com> wrote:
Hello, Thanks for the examples but I noticed that none of the icons in modelEditorIconBar seem to work. Clicking on shaded or wireframe icons have no effect in the viewport. Does anyone know how to fix this problem? I am referring to example1.

Thanks

I've updated the original blog post with a Maya >= 2017 port of that example code:
http://justinfx.com/2011/11/20/mixing-pyqt4-widgets-and-maya-ui-objects/

I tested it in Maya 2018 and it seems like the toolbar icons in the model editor worked just fine. Can you confirm?
 
--
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.

Timothy Kim

unread,
Aug 20, 2018, 9:44:20 AM8/20/18
to python_in...@googlegroups.com

Thank Justin. I don't have access to my code right now to check the differences between mine and this one but this code works perfectly fine. Thanks again.


From: python_in...@googlegroups.com <python_in...@googlegroups.com> on behalf of Justin Israel <justin...@gmail.com>
Sent: Sunday, August 19, 2018 9:37:26 PM
To: python_in...@googlegroups.com
Subject: Re: [Maya-Python] Re: How to embed modelPanel to a pyqt ui (again) ?
 
** Incoming mail from outside The Mill **

Timothy Kim

unread,
Aug 23, 2018, 12:36:00 PM8/23/18
to python_in...@googlegroups.com

Hey Justin,


It seems like putting the paneLayout into a QSplitter causes the issue. I edited your code to add the splitter.





From: python_in...@googlegroups.com <python_in...@googlegroups.com> on behalf of Timothy Kim <tk...@themill.com>
Sent: Monday, August 20, 2018 9:44:08 AM
To: python_in...@googlegroups.com
Subject: [MailingList] Re: [Maya-Python] Re: How to embed modelPanel to a pyqt ui (again) ?
 

Timothy Kim

unread,
Aug 23, 2018, 12:37:26 PM8/23/18
to python_in...@googlegroups.com

Running the code below adds the splitter. Do you know if there's a work around for this?

Thanks

from PySide2 import QtCore, QtWidgets
import shiboken2

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


#class MyDialog(QtWidgets.QDialog):
class MyDialog(QtWidgets.QMainWindow):

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

        #self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.verticalLayout = QtWidgets.QVBoxLayout(self.central_widget)
        self.verticalLayout.setContentsMargins(0,0,0,0)

        # 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(shiboken2.getCppPointer(self.verticalLayout)[0]))
        cmds.setParent(layout)

        paneLayoutName = cmds.paneLayout()
                
        # Find a pointer to the paneLayout that we just created
        ptr = mui.MQtUtil.findControl(paneLayoutName)
        
        # Wrap the pointer into a python QObject
        self.paneLayout = shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)

        self.cameraName = cmds.camera()[0]
        self.modelPanelName = cmds.modelPanel("customModelPanel#", label="ModelPanel Test", cam=self.cameraName)

        
        timeline = cmds.timePort('cameraViewerTimePort')
        time_ptr = mui.MQtUtil.findControl(timeline)
        self.timePaneLayout = shiboken2.wrapInstance(long(time_ptr), QtWidgets.QWidget)

        
        # Find a pointer to the modelPanel that we just created
        ptr = mui.MQtUtil.findControl(self.modelPanelName)
        
        # Wrap the pointer into a python QObject
        self.modelPanel = shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)

        splitter1 = QtWidgets.QSplitter(QtCore.Qt.Vertical)
        
        splitter1.addWidget(self.paneLayout)
        splitter1.addWidget(self.timePaneLayout)
        splitter1.setSizes([500, 200])


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

    def showEvent(self, event):
        super(MyDialog, self).showEvent(event)

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

def show():
    # get a pointer to the maya main window
    ptr = mui.MQtUtil.mainWindow()
    # use sip to wrap the pointer into a QObject
    win = shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)
    d = MyDialog(win)
    d.show()

    return d


try:
    dialog.deleteLater()
except:
    pass    
dialog = show()


From: Timothy Kim
Sent: Thursday, August 23, 2018 12:35:46 PM

Justin Israel

unread,
Aug 23, 2018, 5:43:05 PM8/23/18
to python_in...@googlegroups.com
I don't really have an answer for you on this one. I tried to shuffle things around in your latest code example, and tried even creating an intermediate widget+layout between the splitter and the paneLayout, but the behaviour did not change. Don't forget, this is all a hack on the Maya UI so its not unreasonable for things to work incorrectly :-)



Timothy Kim

unread,
Aug 24, 2018, 9:13:46 AM8/24/18
to python_in...@googlegroups.com

Thanks for looking into Justin.




Sent: Thursday, August 23, 2018 5:42 PM

To: python_in...@googlegroups.com
Subject: Re: [Maya-Python] Re: How to embed modelPanel to a pyqt ui (again) ?
** Incoming mail from outside The Mill **

I don't really have an answer for you on this one. I tried to shuffle things around in your latest code example, and tried even creating an intermediate widget+layout between the splitter and the paneLayout, but the behaviour did not change. Don't forget, this is all a hack on the Maya UI so its not unreasonable for things to work incorrectly :-)



ups "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/BL0PR02MB363517A5490B81A69CEC8B85D3320%40BL0PR02MB3635.namprd02.prod.outlook.com.
For more options, visit https://groups.google.com/d/optout.

--
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/DM5PR02MB36377ECD33C4A72D151B822DD3370%40DM5PR02MB3637.namprd02.prod.outlook.com.
For more options, visit https://groups.google.com/d/optout.

--
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.
Reply all
Reply to author
Forward
0 new messages