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

时间:2019-01-14 22:05:39

标签: python maya qt-signals pyside2

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

要尝试一下,只需运行代码,然后单击“错误”按钮。

我在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()

1 个答案:

答案 0 :(得分:0)

就像我在评论中说的那样,我可以在2017年和2017年的更新2中复制您的错误,但在2018年可以正常工作。

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

有趣的是,静态方法也有同样的问题!如果您尝试从班级内部调用它们,它们将挂起。但是,如果您从类外部调用它,则可以正常工作;或者,如果将所有内容都用try except包装,那么从类内部调用它现在将可以工作。

签出以下代码。我包括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,以查看是否已修补。

希望这会有所帮助!