May 2 2014

Parenting Qt gui’s to the main 3dsMax window (BlurPython)

I had a chance to break down the blurdev “Dialog” class today. This class is a modified QDialog class that automatically handles parenting the dialog to the max window. The way in which the Blur Developers achieve this is by compiling a Qt4 module (QtWinMigrate) that does not ship with either PySide or PyQt4 that can convert the windows handle id of the main max window into a QObject that we can use as a parent. the process is very simple, here’s a snippet…

from blurdev.gui.winwidget import WinWidget
parent = WinWidget.newInstance(blurdev.core.hwnd()) 

Here’s an example built directly into a class that inherits a QMainWindow…

import blurdev
from blurdev.gui.winwidget import WinWidget
from PyQt4 import QtGui,QtCore, uic

class test(QtGui.QMainWindow):
	def __init__(self,parent=None):
		if not parent:
			parent = WinWidget.newInstance(blurdev.core.hwnd()) 
		super(test,self).__init__(parent)
		self.setAttribute(QtCore.Qt.WA_DeleteOnClose )
		self.setMouseTracking( True )
		self.checkScreenGeo = True
		self.aboutToClearPathsEnabled = True

gui = test()
gui.show()

last but not least here’s the example from my previous uic post using this code to parent the window to Max.

from PyQt4 import QtGui, QtCore, uic  
base,form = uic.loadUiType(r'c:\uifiles\mainUI.ui')
class mainApp(base,form):
    def __init__(self,parent=None):
        super(mainApp,self).__init__(parent)
        self.setupUi(self)
        #----
        self.populateList()
        self.connectWidgets()
    #populate a list box...
    def populateList(self):
        self.scnObjects = mxs.objects
        for o in self.scnObjects:self.listWidget.addItem(o.name)
    #-- connect event handlers
    def connectWidgets(self):
        self.listWidget.itemSelectionChanged.connect(self.selectObjects)
        self.pushButton.clicked.connect(self.pressButton)
    #--list box events
    def selectObjects(self):
        sel = []
        mxs.deselect(mxs.objects)
        for i in self.listWidget.selectedItems():
            obj = self.scnObjects[(self.listWidget.indexFromItem(i).row())]
            sel.append(obj)
        mxs.select(sel)
        mxs.ForceCompleteRedraw()
    #-- button event
    def pressButton(self):
        sel = self.listWidget.selectedItems()
        QtGui.QMessageBox.about(self,'QtMessage',"%i objects selected" % len(mxs.selection))

def open():
	from blurdev.gui.winwidget import WinWidget
	app = mainApp(parent=WinWidget.newInstance(blurdev.core.hwnd()))
	app.show()
	return app

test = open()

Give it a go, i hope it works for you. Until next time, happy coding!

4 Responses to “Parenting Qt gui’s to the main 3dsMax window (BlurPython)”

  • Malcom Says:

    Good article, but have you used the python implementation in Max 2015? We are looking to move away from the Blur python we currently use in favour of the Autodesk version but the pyside UI example has no code that parents it to the main max window. Is this something that you have looked at? It seems odd that they would give the ui creation code but nothing to parent it as the hwnd functionality of Blur Python. If you have any information, it would be very welcome

    • Los Says:

      I have not tried MaxPlus in a long time.
      One of the issues is that 3ds max is not a written in Qt, and the main windows is actually a .net window. Qt its self does have a library for wrapping .net windows around a QtWrapper Widget which facilitates integration. Unfortunately this is not part of PySide or PyQt distribution. The guys at Blur got around it by extending the PyQt binding in Blur Python to expose this library (QtWinMigrate AKA blurdev.gui.winwidget).
      PySide intergration for max was not actually properly developed, it was rushed 🙁 so they never exposed this particular library.
      I’m not sure autodesk has any plans of further developing python in max, which is sad since the current state is not very good compared to blur python.
      Maya and Nuke, are actually written in Qt which is why maya can use the shiboken library, and nuke can actually just uses QtApplication.activeWindow
      Sorry I couldn’t be more helpful.
      if you do find the QtWinMigrate in max 2015 let me know please 🙂

      • Malcom Says:

        I was hoping that the new 2015 implementation would be better as it is one of the “new features” they are touting with the new release. I am in the process of investigating this “new” version and so far have found it to possibly be still somewhat underdeveloped. I have been trying to see if I can utilise the Maya method and shiboken, if I get any results, I will definitely post back any findings. Seems so weird that they have not taken the opportunity to bring max in line with the Qt standard so many other apps are using. Autodesk own maya, so why they have not done so is very odd.

        Thanks

        • Los Says:

          Yeah,
          I tried the shiboken maya method with bad results…
          For shiboken method to work the handle needs to point to a c++ qt window.
          Which max is not 🙁
          Its the same problem in cinema and probaly houdini as well, sence they do not ship with pyside 🙁

Leave a Reply