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.
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:
Normally one creates a PySide application object in a script using QtGui.QApplication(). However, in 3ds Max, there is already a PySide application running, so you get a handle for that object like this:
QtGui.QApplication.instance()
Nodes created within a script may not appear in Max until the script exits, unless you force a viewport update. You can do so with MaxPlus.ViewportManager.ForceCompleteRedraw() or MaxPlus.ViewportManager.RedrawViews().
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()