PySide Widget for 3dsMax and Modo
Question: I'm trying to create a simple QT app using PySide and Python that I want it to
run as a 3dsMax script, a Modo script and a stand-alone app if needed. So,
I've saved the following files in my D:\PyTest. It's just a QLabel for this
test.

When I run it (_TestWidget.py_) as a stand-alone it works fine. When I start
it (_ModoStart.py_) from Modo it starts correctly but if I try to click
anywhere in Modo it crashes the whole window. In 3dsMax I get the following
error: **Traceback (most recent call last): File "D:/PyTest\TestWidget.py",
line 13, in SystemExit: -1**

Any ideas how I can make it work?

Thanks,  
Nick

_TestWidget.py_

    
    
    import sys
    from PySide import QtGui
    
    
    def open_widget(app, parent_handle=None):
        w = QtGui.QLabel()
        w.setText("My Widget")
        w.show()
    
        if parent_handle is not None:
            w.setParent(parent_handle)
    
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        open_widget(QtGui.QApplication(sys.argv))
    

_MaxStart.py_

    
    
    import sys
    
    FileDir = 'D:/PyTest'
    if FileDir not in sys.path:
        sys.path.append(FileDir)
    
    #Rest imports
    from PySide import QtGui
    import MaxPlus
    import TestWidget
    reload(TestWidget)
    
    app = QtGui.QApplication.instance()
    parent_handle = QtGui.QWidget(MaxPlus.GetQMaxWindow())
    TestWidget.open_widget(app, parent_handle)
    

_ModoStart.py_

    
    
    import sys
    
    FileDir = 'D:/PyTest'
    if FileDir not in sys.path:
        sys.path.append(FileDir)
    
    #Rest imports
    from PySide import QtGui
    import TestWidget
    reload(TestWidget)
    
    app = QtGui.QApplication.instance()
    TestWidget.open_widget(app)
    

**UPDATE:**  
I also tried to have one file for all three options (3dsMax/Modo/Stand-alone).
It seems that it works fine for 3dsMax and Stand-Alone, but in Modo, if I
click outside the Widget or if I try to close it, Modo instantly crashes.

    
    
    import sys
    import traceback
    from PySide import QtGui
    handle = None
    appMode = None
    try:
        import MaxPlus
        appMode = '3dsMax'
        handle = MaxPlus.GetQMaxWindow()
    except:
        try:
            import lx
            appMode = 'Modo'
        except:
            appMode = 'StandAlone'
    
    
    app = QtGui.QApplication.instance()
    if not app:
        app = QtGui.QApplication([])
    
    
    def main():
        w = QtGui.QLabel(handle)
        w.setText("My Widget")
        w.resize(250, 100)
        w.setWindowTitle('PySide Qt Window')
        w.show()
    
        try:
            sys.exit(app.exec_())
        except Exception, err:
            traceback.print_exc()
            pass
    
    main()
    


Answer: Ok, with a little help from The Foundry I have a working version. They gave me
this very useful link <http://sdk.luxology.com/wiki/CustomView>

_3dsMax.py_

    
    
    from PySide import QtGui
    import MaxPlus
    import sys
    ui_dir = r'D:/PyTest/SubFolder/'
    if not ui_dir in sys.path:sys.path.insert(0,ui_dir)
    import ToolboxUI
    reload(ToolboxUI)
    
    
    parent = MaxPlus.GetQMaxWindow()
    
    w = QtGui.QWidget(parent)
    ToolboxUI.create_layout(w, '3dsMax')
    w.show()
    

_Modo.py_

    
    
    import lx
    import lxifc
    import sys
    ui_dir = r'D:/PyTest/SubFolder/'
    if not ui_dir in sys.path:sys.path.insert(0,ui_dir)
    import ToolboxUI
    reload(ToolboxUI)
    
    
    class MyButtonTest(lxifc.CustomView):
        def customview_Init(self, pane):
            if pane is None:
                return False
    
            custom_pane = lx.object.CustomPane(pane)
    
            if custom_pane.test() is False:
                return False
    
            # get the parent object
            my_parent = custom_pane.GetParent()
    
            # convert to PySide QWidget
            p = lx.getQWidget(my_parent)
    
            # Check that it succeeds
            if p is not None:
                ToolboxUI.create_layout(p, 'Modo')
                return True
    
            return False
    
    try:
        lx.bless(MyButtonTest, "My Button Test")
    except:
        pass
    

_StandAlone.py_

    
    
    from PySide import QtGui
    import sys
    import ToolboxUI
    
    app = QtGui.QApplication([])
    
    w = QtGui.QWidget()
    ToolboxUI.create_layout(w, 'StandAlone')
    w.show()
    
    sys.exit(app.exec_())
    

_ToolboxUI.py_

    
    
    from PySide import QtGui
    appMode = None
    
    
    def on_clicked(side):
        print "Hello from the " + side + " side: " + appMode
    
    
    def left_click():
        on_clicked("left")
    
    
    def center_click():
        on_clicked("center")
    
    
    def right_click():
        on_clicked("right")
    
    
    def create_layout(my_window, am):
        global appMode
        appMode = am
    
        buttonLayout = QtGui.QHBoxLayout()
        buttonLayout.setSpacing(0)
    
        leftButton = QtGui.QPushButton("Left")
        leftButton.setProperty("group", "left")
        leftButton.clicked.connect(left_click)
    
        rightButton = QtGui.QPushButton("Right")
        rightButton.setProperty("group", "right")
        rightButton.clicked.connect(right_click)
    
        centerButton = QtGui.QPushButton("Center")
        centerButton.setProperty("group", "center")
        centerButton.clicked.connect(center_click)
    
        buttonLayout.addWidget(leftButton)
        buttonLayout.addWidget(centerButton)
        buttonLayout.addWidget(rightButton)
    
        my_window.setLayout(buttonLayout)
    

