2

I'm trying to create a simple QT app using PySide and Python that I want it to run as a 3dsMax script, a Modo script and a stand-alone app if needed. So, I've saved the following files in my D:\PyTest. It's just a QLabel for this test.

When I run it (TestWidget.py) as a stand-alone it works fine. When I start it (ModoStart.py) from Modo it starts correctly but if I try to click anywhere in Modo it crashes the whole window. In 3dsMax I get the following error: Traceback (most recent call last): File "D:/PyTest\TestWidget.py", line 13, in SystemExit: -1

Any ideas how I can make it work?

Thanks,
Nick

TestWidget.py

import sys
from PySide import QtGui


def open_widget(app, parent_handle=None):
    w = QtGui.QLabel()
    w.setText("My Widget")
    w.show()

    if parent_handle is not None:
        w.setParent(parent_handle)

    sys.exit(app.exec_())


if __name__ == '__main__':
    open_widget(QtGui.QApplication(sys.argv))

MaxStart.py

import sys

FileDir = 'D:/PyTest'
if FileDir not in sys.path:
    sys.path.append(FileDir)

#Rest imports
from PySide import QtGui
import MaxPlus
import TestWidget
reload(TestWidget)

app = QtGui.QApplication.instance()
parent_handle = QtGui.QWidget(MaxPlus.GetQMaxWindow())
TestWidget.open_widget(app, parent_handle)

ModoStart.py

import sys

FileDir = 'D:/PyTest'
if FileDir not in sys.path:
    sys.path.append(FileDir)

#Rest imports
from PySide import QtGui
import TestWidget
reload(TestWidget)

app = QtGui.QApplication.instance()
TestWidget.open_widget(app)

UPDATE:
I also tried to have one file for all three options (3dsMax/Modo/Stand-alone). It seems that it works fine for 3dsMax and Stand-Alone, but in Modo, if I click outside the Widget or if I try to close it, Modo instantly crashes.

import sys
import traceback
from PySide import QtGui
handle = None
appMode = None
try:
    import MaxPlus
    appMode = '3dsMax'
    handle = MaxPlus.GetQMaxWindow()
except:
    try:
        import lx
        appMode = 'Modo'
    except:
        appMode = 'StandAlone'


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


def main():
    w = QtGui.QLabel(handle)
    w.setText("My Widget")
    w.resize(250, 100)
    w.setWindowTitle('PySide Qt Window')
    w.show()

    try:
        sys.exit(app.exec_())
    except Exception, err:
        traceback.print_exc()
        pass

main()
Nick
  • 221
  • 2
  • 12
  • Can you post the full traceback? – Tom Myddeltyn Jun 20 '16 at 12:35
  • how do I do that (sorry I'm new to python)? I've tried by two things in MaxStart.py import traceback . . try: app = QtGui.QApplication.instance() parent_handle = QtGui.QWidget(MaxPlus.GetQMaxWindow()) TestWidget.open_widget(app, parent_handle) except Exception, err: traceback.print_exc() and in TestWidget.py import traceback . . . try: sys.exit(app.exec_()) except Exception, err: traceback.print_exc() Nothing seem to make any difference – Nick Jun 20 '16 at 12:46
  • Oh, so in 3dsmax it is only telling you that one line then? Sorry I am not so familiar with 3dsmax. – Tom Myddeltyn Jun 20 '16 at 14:02
  • No worries, thanks for trying. I've updated my post though. I found a way to make it work both 3dsMax and stand-alone but in Modo, even though it starts fine, when I click outside the widget or if try to close it, Modo crashes. :/ – Nick Jun 20 '16 at 15:37
  • http://community.thefoundry.co.uk/discussion/topic.aspx?f=119&t=74542 Not sure if you read this thread. It is also a bit dated, so not sure if entirely pertinent. – Tom Myddeltyn Jun 20 '16 at 15:55
  • Nice find @busfault, it looks related. I've emailed a guy at The Foundry at the same time I posted the update here. Fingers crossed he'll get back to me. – Nick Jun 20 '16 at 16:09
  • How are you running python inside 3dsmax? Are you using the Autodesk plugin or the Blur Studio Py3dsMax plugin? – Brendan Abel Jun 21 '16 at 01:13
  • I'm using the new (3dsMax 2017) implementation which I think it's equivalent to Blur's. In 2017 you can now execute python scripts directly from the IDE. – Nick Jun 21 '16 at 07:11

1 Answers1

2

Ok, with a little help from The Foundry I have a working version. They gave me this very useful link http://sdk.luxology.com/wiki/CustomView

3dsMax.py

from PySide import QtGui
import MaxPlus
import sys
ui_dir = r'D:/PyTest/SubFolder/'
if not ui_dir in sys.path:sys.path.insert(0,ui_dir)
import ToolboxUI
reload(ToolboxUI)


parent = MaxPlus.GetQMaxWindow()

w = QtGui.QWidget(parent)
ToolboxUI.create_layout(w, '3dsMax')
w.show()

Modo.py

import lx
import lxifc
import sys
ui_dir = r'D:/PyTest/SubFolder/'
if not ui_dir in sys.path:sys.path.insert(0,ui_dir)
import ToolboxUI
reload(ToolboxUI)


class MyButtonTest(lxifc.CustomView):
    def customview_Init(self, pane):
        if pane is None:
            return False

        custom_pane = lx.object.CustomPane(pane)

        if custom_pane.test() is False:
            return False

        # get the parent object
        my_parent = custom_pane.GetParent()

        # convert to PySide QWidget
        p = lx.getQWidget(my_parent)

        # Check that it succeeds
        if p is not None:
            ToolboxUI.create_layout(p, 'Modo')
            return True

        return False

try:
    lx.bless(MyButtonTest, "My Button Test")
except:
    pass

StandAlone.py

from PySide import QtGui
import sys
import ToolboxUI

app = QtGui.QApplication([])

w = QtGui.QWidget()
ToolboxUI.create_layout(w, 'StandAlone')
w.show()

sys.exit(app.exec_())

ToolboxUI.py

from PySide import QtGui
appMode = None


def on_clicked(side):
    print "Hello from the " + side + " side: " + appMode


def left_click():
    on_clicked("left")


def center_click():
    on_clicked("center")


def right_click():
    on_clicked("right")


def create_layout(my_window, am):
    global appMode
    appMode = am

    buttonLayout = QtGui.QHBoxLayout()
    buttonLayout.setSpacing(0)

    leftButton = QtGui.QPushButton("Left")
    leftButton.setProperty("group", "left")
    leftButton.clicked.connect(left_click)

    rightButton = QtGui.QPushButton("Right")
    rightButton.setProperty("group", "right")
    rightButton.clicked.connect(right_click)

    centerButton = QtGui.QPushButton("Center")
    centerButton.setProperty("group", "center")
    centerButton.clicked.connect(center_click)

    buttonLayout.addWidget(leftButton)
    buttonLayout.addWidget(centerButton)
    buttonLayout.addWidget(rightButton)

    my_window.setLayout(buttonLayout)
Nick
  • 221
  • 2
  • 12