I thought I would come back to this thread to update how I now approach the issue -if only to make sure I am understanding things correctly. My solution is a just variation on the suggestions above. Here is the complete module. The approach is explained in the comments and doc strings.
'''
widget.py
a module for QtWidget class that can launch stand-alone or from maya
The two basic obstacles to this are:
1: the QApplication : stand-alone we have to instantiate a QApplication object, in Maya we do not (Maya Main Window is the QApplication object)
2: the QWidget instances `parent` argument : stand-alone = None, in maya, = reference to Maya Main Window
Each obstacle is tackled with helper functions:
1: launch_widget()
2: get_parent()
*note : We use Maya 2017 so this is using Pyside2.
for pyside you'll need to use QtGui instead fo QtWidgets (untested)
'''
from PySide2 import QtWidgets
def get_parent():
'''
get a value for a QtQWidget's parent
if in Maya, returns MayaMainWindow Qt object
else returns None
:return: None or MayaWindow Qt Object
'''
parent=None
try:
parent = {o.objectName(): o for o in QtWidgets.qApp.topLevelWidgets()}["MayaWindow"]
except Exception as e:
print e
pass
print "parent={}".format(parent)
return parent
class MyWidget(QtWidgets.QDialog):
'''
A basic QtWidget class.
The only unusual bit is using get_parent() in the __init__()
'''
def __init__(self, parent=get_parent(), message="default text"):
super( MyWidget, self).__init__(parent)
self.label=QtWidgets.QLabel()
layout=QtWidgets.QVBoxLayout()
layout.addWidget(self.label)
self.setLayout(layout)
self.label.setText(message)
self.setWindowTitle("MyWidget")
def launch_widget(message):
'''
a wrapper function for convenience
Save this module as 'widget.py' and use :
import widget
widget.launch_widget("my message")
it works the same in and outside of maya
:param message: str
:return: None
'''
# try standalone
try:
app = QtWidgets.QApplication([])
widget = MyWidget(message=message)
widget.show()
app.exec_()
# Within in Maya, QApplication exists and we get a RuntimeError, so try running inside of maya
except RuntimeError:
widget = MyWidget(message=message)
widget.exec_() # QDialog instances have the exec_() method. For other QtWidgets use widget.show()
# for stand-alone testing
if __name__ == '__main__':
launch_widget("I Stand Alone...")
Save this module as āwidget.pyā and use :
import widget
widget.launch_widget("my message")
it works the same in and outside of maya.
Iāve used this approach on a few tools so far without issue, but if anyone spots any serious flaws inn my code or my thinking Iād love to hear about it.