【问题标题】:PySide emit signal causes python to crashPySide 发出信号导致 python 崩溃
【发布时间】:2012-01-09 21:58:10
【问题描述】:

我正在阅读“使用 Python 和 Qt 进行快速 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 行正常,然后在发射行窗口报告 Python。 exe崩溃了。我得到的错误是“python.exe 已停止工作”,控制台报告“进程已完成,退出代码 -1073741819”

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

【问题讨论】:

  • 尝试了另一个执行发射的程序,同样的事情......

标签: python signals-slots pyside


【解决方案1】:

SIGNAL("atzero(int)") 替换checkzeroForm.__init__ 中的SIGNAL("atzero"),因为您声明它的方式,它没有任何参数。

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

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_()

【讨论】:

  • 谢谢,解决了。但是,这本书特别说不要放任何括号,说它会产生“短路”信号。我会进一步研究,感谢您的回答。
  • 猜猜“短路”信号是 PyQT 没有为 PySide 带来的功能。对于未来的读者来说,这模糊地触及了它,但足以让我知道 PySide 没有发生这种情况 - developer.qt.nokia.com/wiki/…
  • 从这个意义上说不知道。我还试图将您的代码翻译成 PyQt/PySide 中的新型 Slot/Signal 语法,但由于某种原因,它把它们翻译错了。可能是我的旧版本...
  • @Mike:我添加了一个使用新样式 Slot/Signal 语法的代码版本。之前因为我使用的是 PySide 0.4,所以它不能马上工作,但在另一台计算机上我有 1.1 并且按预期工作。
  • 谢谢@Ricardo。它有助于在旧方式旁边看到新的风格。感谢您花时间写下来。
【解决方案2】:

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

您使用的这本书是专门为 PyQt4 编写的,因此您在使用它时可能需要注意 PySide 和 PyQt4 之间的区别。例如,请参阅here

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

您应该注意的另一件事是,您正在使用的信号/槽语法已被更 Pythonic 的新式语法所取代。因此,在某些时候,如果您的书没有涵盖该指南,则值得阅读 here 的指南。

【讨论】:

  • 谢谢。我知道这本书是为 PyQt4 写的,但刚接触它并不太了解它与 PySide 之间的区别。我将研究新的信号/槽语法,感谢指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-06
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多