为什么我的 pyqt 信号错误会冻结 ui,直到另一个 python 函数被调用

Why do my errors from pyqt signals freeze the ui until another python function gets called

在 Maya 2016 中一切正常。但是在 Maya 2017 中(在我完成所有 pyqt 转换之后),从 qt 信号调用的函数中发生的任何错误都不会立即显示出来。然后如果我在脚本编辑器中 运行 另一个代码,例如 "print 0",就会出现上一个函数的错误

要试用,只需 运行 代码,然后单击按钮 "error"。

我在 Windows 和 Mac 上试过了。还请一位朋友试穿他的 - 他也遇到了同样的问题。同样,在 Maya 2016 上一切正常。该问题仅发生在 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()

正如我在评论中所说,我可以在 2017 年和 2017 年更新 2 中复制您的错误,但在 2018 年工作得很好。

幸运的是,有一个足够简单的解决方案,您只需将您的方法移出 __init__ 即可使其成为普通实例方法。现在这样做会按预期出错。 (老实说,在 __init__ 中嵌套函数有点奇怪,不管它是否有问题我都会移动它)

有趣的是,静态方法也有同样的问题!如果您尝试从 class 内部调用它们,它们将挂起。但是如果你从 class 外部调用它,它工作正常,或者如果你用 try except 包裹它,它现在在从 class 内部调用时可以工作.

检查以下代码。我包括了 3 个案例,一个实例化方法,一个静态方法,以及一个用 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.

所有这些都在 Maya 2018 中工作,但静态方法将在 2017 中失败。 希望您可以避免使用静态方法,因为将其全部包装在 try except 中并不是一个实用的解决方案。你也可以试试把你的Maya更新到2017 update 4看看有没有补丁。

希望对您有所帮助!