PySide发出信号导致python崩溃

时间:2012-01-09 21:58:11

标签: python signals-slots pyside

我正在阅读“使用Python和Qt进行Rapid Gui编程”一书,并且在信号/插槽项目上遇到了问题。我已经下载了作者代码以与我自己进行比较,但它看起来都一样,但是,当我从派生的旋转框类发出信号时,python就崩溃了。这是我的整个代码:

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class ZeroSpinBox(QSpinBox):
    zeros = 0

    def __init__(self, parent=None):
        super(ZeroSpinBox, self).__init__(parent)
        self.connect(self, SIGNAL("valueChanged(int)"), self.checkzero)

    def checkzero(self):
        if self.value() == 0:
            self.zeros += 1
            self.emit(SIGNAL("atzero"), self.zeros)

class Form(QDialog):
    def __init__(self, parent= None):
        super(Form, self).__init__(parent)

        dial = QDial()
        dial.setNotchesVisible(True)
        spinbox = ZeroSpinBox()
        spinbox.setRange(0,200)
        dial.setRange(0,200)

        layout = QHBoxLayout()
        layout.addWidget(dial)
        layout.addWidget(spinbox)
        self.setLayout(layout)

        self.connect(dial, SIGNAL("valueChanged(int)"), spinbox, SLOT("setValue(int)"))
        self.connect(spinbox, SIGNAL("valueChanged(int)"), dial, SLOT("setValue(int)"))
        self.connect(spinbox, SIGNAL("atzero"), self.announce)

        self.setWindowTitle("Signals and Slots Part 2")

    def announce(self, zeros):
        print "ZeroSpinBox has been at zero %d times" % zeros


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    app.exec_()

我的问题发生在spinbox下降到零时,checkzero(self)方法(ZeroSpinBox类)被调用,self.zeros + = 1行是ok,然后在emit行窗口报告Python。 exe崩溃了。我得到的错误是“python.exe已停止工作”,控制台报告“进程已完成退出代码-1073741819”

知道为什么会这样吗?这是Python 2.7.2和PyQT4 w / PySide。

2 个答案:

答案 0 :(得分:4)

SIGNAL("atzero")SIGNAL("atzero(int)")中用checkzero替换Form.__init__,因为您宣布它的方式,它没有任何争议。

编辑:您的代码采用“新式”,

import sys
from PySide.QtCore import *
from PySide.QtGui import *

class ZeroSpinBox(QSpinBox):
    zeros = 0

    def __init__(self, parent=None):
        super(ZeroSpinBox, self).__init__(parent)
        self.valueChanged.connect(self.checkzero)

    atzero = Signal(int)

    def checkzero(self):
        if self.value() == 0:
            self.zeros += 1
            self.atzero.emit(self.zeros)

class Form(QDialog):
    def __init__(self, parent= None):
        super(Form, self).__init__(parent)

        dial = QDial()
        dial.setNotchesVisible(True)
        spinbox = ZeroSpinBox()
        spinbox.setRange(0,200)
        dial.setRange(0,200)

        layout = QHBoxLayout()
        layout.addWidget(dial)
        layout.addWidget(spinbox)
        self.setLayout(layout)

        dial.valueChanged.connect(spinbox.setValue)
        spinbox.valueChanged.connect(dial.setValue)
        spinbox.atzero.connect(self.announce)

        self.setWindowTitle("Signals and Slots Part 2")

    @Slot(int)
    def announce(self, zeros):
        print "ZeroSpinBox has been at zero %d times" % zeros


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Form()
    form.show()
    app.exec_()

答案 1 :(得分:2)

这是由于PySide和PyQt4之间存在差异,记录为here(实际上,严格来说,这是PySide中的一个错误 - 使用不支持的信号语法形式会产生错误,不会导致应用程序崩溃)。

您使用的书是专为PyQt4编写的,因此您可能需要了解PySide和PyQt4在使用时的区别。例如,请参阅here

请注意,你的脚本的PyQt4版本工作正常,有或没有信号的括号部分 - 重要的是它们是相同的。但是,这仅适用于用户定义的信号 - 对于预定义的Qt信号和插槽,您必须始终包含签名的带括号的部分。

您应该注意的另一件事是,您使用的信号/插槽语法已经被更加pythonic的新式语法所取代。所以,在某些时候,如果你的书没有涵盖它,那么阅读here所获得的指导是值得的。