0

In Maya 2016 everything is fine. But in Maya 2017 (after I did all the pyqt conversions), any Error happening in a function called from a qt signal doesn't get shown immediately. Then if I run another code in the script editor, such as "print 0", the error from the previous function comes up

To try it out, simply run the code, and click the button "error".

I tried it on Windows and Mac. Also asked a friend to try on his - and he had same issue. Again, on Maya 2016 it's all fine. The issue is only happening in Maya 2017

from PySide2 import QtWidgets, QtGui, QtCore
from shiboken2 import wrapInstance
import maya.OpenMayaUI as mui


mainWin = None

def showUI():
    global mainWin
    if mainWin != None:
        print "reloading UI..."
        mainWin.close()
    mainWin = myWindow()
    mainWin.show()


def getMayaWindow():
    ptr = mui.MQtUtil.mainWindow()
    return wrapInstance(long(ptr), QtWidgets.QWidget)


class myWindow(QtWidgets.QDialog):

    def __init__(self, parent=getMayaWindow()):

        super(myWindow, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint)

        def funcApply():
            oooo # this should error!

        self.layout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom, self)
        self.testButton = QtWidgets.QPushButton('error')
        self.layout.addWidget(self.testButton)
        self.testButton.clicked.connect(funcApply)

showUI()
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Tom
  • 15
  • 5
  • 1
    Just speculation; but may be a bug introduced with the shift from Qt 4 to Qt 5... Are you also seeing it in 2018? Just tested it in 2018.5, and I get an error immediately `# NameError: global name 'oooo' is not defined` – Morten Jan 15 '19 at 19:15
  • 1
    Unable to replicate the issue in Maya 2018 on Linux – Green Cell Jan 16 '19 at 01:59
  • I also believe that it is a bug that came with the shift from Qt4 to Qt5 - but what confuses me is that I'm the only one with that issue. Because the code for this UI is relatively simple. And thanks for testing it with maya2018 - maybe I'll have to skip 2017 and go to 2018.. – Tom Jan 16 '19 at 21:37
  • Woah, confirmed for 2017 on Linux. I'll report back if I find any solutions. This is a pretty nasty bug, how could they let this slip! It's also a bug with Maya 2017 Update 2. – Green Cell Jan 17 '19 at 02:21

1 Answers1

0

Like I said in the comments, I can replicate your bug in 2017 and 2017 update 2, but works perfectly fine in 2018.

Luckily there's an easy enough solution where you just need to move your method out of the __init__ to make it a normal instance method. Doing this now errors as expected. (Honestly having a nested function inside __init__ is a bit weird anyhow, I'd move it regardless if it was buggy)

Interesting enough, static methods have the same issue! If you try to call them from inside your class, they'll hang. But if you call it from outside the class it works ok, or if you wrap it all with a try except it will now work when being called from inside the class.

Check out the following code. I included 3 cases, an instanced method, a static method, and a static method wrapped with a try except:

from PySide2 import QtWidgets, QtGui, QtCore
from shiboken2 import wrapInstance
import maya.OpenMayaUI as mui


mainWin = None


def showUI():
    global mainWin
    if mainWin != None:
        print "reloading UI..."
        mainWin.close()
    mainWin = myWindow()
    mainWin.show()


def getMayaWindow():
    ptr = mui.MQtUtil.mainWindow()
    return wrapInstance(long(ptr), QtWidgets.QWidget)


class myWindow(QtWidgets.QDialog):

    def __init__(self, parent=getMayaWindow()):

        super(myWindow, self).__init__(parent, QtCore.Qt.WindowStaysOnTopHint)

        # Works.
        self.testButton = QtWidgets.QPushButton('error')
        self.testButton.clicked.connect(self.funcApply)

        # Fails.
        self.testButton2 = QtWidgets.QPushButton('error static method')
        self.testButton2.clicked.connect(self.staticFuncApply)

        # Works.
        self.testButton3 = QtWidgets.QPushButton('error static method with try/except')
        self.testButton3.clicked.connect(self.staticTryExceptFuncApply)

        self.layout = QtWidgets.QBoxLayout(QtWidgets.QBoxLayout.TopToBottom, self)
        self.layout.addWidget(self.testButton)
        self.layout.addWidget(self.testButton2)
        self.layout.addWidget(self.testButton3)
        self.setLayout(self.layout)  # Normally need to specify what layout this widget needs to use.

    # Move this out and make it a normal instanced method.
    # This will work as expected.
    def funcApply(self):
        oooo # this should error!

    # Static methods still broken, but ok in Maya 2018.
    @staticmethod
    def staticFuncApply():
        oooo

    # Static methods wrapped with try except works.
    @staticmethod
    def staticTryExceptFuncApply():
        try:
            oooo
        except Exception as e:
            print e


showUI()

# myWindow.staticFuncApply()  # Calling static method outside of class works ok.

All of these work in Maya 2018, but the static method will fail on 2017. Hopefully you can avoid using static methods, as wrapping it all in a try except is not a practical solution. You can also try to update your Maya to 2017 update 4 to see if it's patched up.

Hope this helps!

Green Cell
  • 4,677
  • 2
  • 18
  • 49
  • yeah, that was it - thanks for finding it out! It'll be tricky to convert all my code, since in some situations I'm creating functions procedurally inside for loops - but I'm sure I'll find a way. As for the try-except statements, I also noticed that he catches them properly. But if you raise the error in the except statement, you have the same issue – Tom Jan 17 '19 at 07:10
  • Maybe for simple nested functions you can replace them with `lambda`? Ah well, glad you at least got a direction to go off of now. Or convince your employer to switch to 2018 :P – Green Cell Jan 17 '19 at 08:24
  • Nope, lambdas have same issue. But I'll find a way. Will just have to change around a few things. – Tom Jan 17 '19 at 18:35
  • ended up just creating dynamic attributes on the buttons, and then creating my own button class that inherits QPushButton. And in that the mouseReleaseEvent() does the magic that normally the clicked signaled function would do. So everything is good again. – Tom Jan 17 '19 at 19:26