Autodesk 3ds Max ships with a pre-built version of PySide 2.0 compatible with Python 2.7.15. 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 dockable widget:
''' Demonstrates how to ceate a QDockWidget with PySide2 for use in 3ds Max ''' from PySide2 import QtCore from PySide2 import QtGui from PySide2 import QtWidgets import pymxs def make_cylinder(): cyl = pymxs.runtime.Cylinder(radius=10, height=30) pymxs.runtime.redrawViews() return class PyMaxDockWidget(QtWidgets.QDockWidget): def __init__(self, parent=None): super(PyMaxDockWidget, self).__init__(parent) self.setWindowFlags(QtCore.Qt.Tool) self.setWindowTitle('Pyside Qt Dock Window') self.initUI() self.setAttribute(QtCore.Qt.WA_DeleteOnClose) def initUI(self): main_layout = QtWidgets.QVBoxLayout() label = QtWidgets.QLabel("Click button to create a cylinder in the scene") main_layout.addWidget(label) cylinder_btn = QtWidgets.QPushButton("Cylinder") cylinder_btn.clicked.connect(make_cylinder) main_layout.addWidget(cylinder_btn) widget = QtWidgets.QWidget() widget.setLayout(main_layout) self.setWidget(widget) self.resize(250, 100) def main(): pymxs.runtime.resetMaxFile(pymxs.runtime.name('noPrompt')) mainWindow=QtWidgets.QWidget.find(pymxs.runtime.windows.getMAXHWND()) w = PyMaxDockWidget(parent=mainWindow) w.setFloating(True) w.show() if __name__ == '__main__': main()
Notes:
MaxPlus provides a facility for loading UI files created by Qt Designer: MaxPlus.LoadUiType(). This example looks for a ui file named test.ui located under scripts/Python/ui/ and loads it.
Note: If you use the Python global __file__ to find the target ui file, the global will only evaluate when using the Scripting > Run Script command. In this example, we use the MAXScript getDir() function, which will work in any context.
import MaxPlus, os from PySide2 import QtWidgets from PySide2 import QtCore from pymxs import runtime as rt def makeTeapot(): rt.teapot() class TestDialog(QtWidgets.QDialog): def __init__(self, ui_class, parent=MaxPlus.GetQMaxMainWindow()): QtWidgets.QDialog.__init__(self, parent) self.ui=ui_class() self.ui.setupUi(self) self.ui.pushButton.clicked.connect(makeTeapot) def main(): script_dir = rt.getDir(rt.name('scripts')) ui_path = os.path.join(script_dir, 'Python', 'ui','test.ui') ui_class, base_class = MaxPlus.LoadUiType(ui_path) instance = TestDialog(ui_class) instance.show() if __name__ == '__main__': main()