Using PySide

Autodesk 3ds Max ships with a pre-built version of PySide 2.0 compatible with Python 2.7.6. This version includes all standard PySide modules.

Example PySide Script

The following simple example shows how to obtain a handle for the PySide application object and create a widget:

'''
    Demonstrates how to create a QWidget with PySide and attach it to the 3dsmax main window.
'''

from PySide import QtGui
import MaxPlus


class _GCProtector(object):
    widgets = []

def make_cylinder():
    obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Cylinder)
    obj.ParameterBlock.Radius.Value = 10.0
    obj.ParameterBlock.Height.Value = 30.0
    node = MaxPlus.Factory.CreateNode(obj)
    time = MaxPlus.Core.GetCurrentTime()
    MaxPlus.ViewportManager.RedrawViews(time)
    return

app = QtGui.QApplication.instance()
if not app:
    app = QtGui.QApplication([])

def main():     
    MaxPlus.FileManager.Reset(True)

    w = QtGui.QWidget(MaxPlus.GetQMaxWindow())
    _GCProtector.widgets.append( w )
    w.resize(250, 100)
    w.setWindowTitle('PySide Qt Window')

    main_layout = QtGui.QVBoxLayout()
    label = QtGui.QLabel("Click button to create a cylinder in the scene")
    main_layout.addWidget(label)

    cylinder_btn = QtGui.QPushButton("Cylinder")
    cylinder_btn.clicked.connect(make_cylinder)
    main_layout.addWidget(cylinder_btn)

    textEdit = QtGui.QLineEdit()
    textEdit.setText("Edit box")
    main_layout.addWidget(textEdit)

    w.setLayout( main_layout )
    w.show()


if __name__ == '__main__':
    main()

Notes:

Loading Qt UI Files

MaxPlus provides a facility for loading UI files created by Qt Designer: MaxPlus.LoadUiType(). For example (from demoPySideLoader.py):

import MaxPlus
import os
from PySide2.QtWidgets import QTabWidget

class TestWidget(QTabWidget):
    def __init__(self, ui_class, parent=None):
        QTabWidget.__init__(self, parent)
        self.ui= ui_class()
        self.ui.setupUi(self)

def test_load_ascii_ui_path(ui_path):
    ui_class, base_class = MaxPlus.LoadUiType(ui_path)
    instance = TestWidget(ui_class)
    instance.show()
    instance.close()

def test_load_ui():
    ui_path = os.path.join(os.path.dirname(__file__), "test_ui.ui")
    test_load_ascii_ui_path(ui_path)
    # test unicode encoding
    test_load_ascii_ui_path(u'%s' % ui_path)
    # test a unicode encoding with non-ascii characters
    try:
        test_load_ascii_ui_path(u'D:/你好')
    except UnicodeEncodeError:
        pass
    else:
        print "Error: unexpected exception"


if __name__ == "__main__":
    test_load_ui()