0

好吧,我对 Qt 很熟悉,但是在使用 PyQt 时,信号/槽的语法真的让我很困惑。使用 C++/Qt 时,编译器会提示您在信号/插槽方面有什么错误,但 PyQt 默认配置不会提示错误。有没有办法或诸如调试触发模式使 PyQt 显示更多信息?代码如下:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time

class workThread(QThread):

    def __init__(self,parent = None):
        super(workThread,self).__init__(parent)
        self.mWorkDoneSignal = pyqtSignal() ## some people say this should be defined as clas member, however, I defined it as class member and still fails.

    def run(self):
        print "workThread start"
        time.sleep(1)
        print "workThread stop"
        print self.emit(SIGNAL("mWorkDoneSignal"))

class MainWidget(QWidget):
    def __init__(self , parent = None):
        super(MainWidget,self).__init__(parent)

    @pyqtSlot()
    def display(self):
        print "dispaly"

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    c = workThread()
    d = MainWidget()
    ##In Qt, when using QObject::connect or such things, the return value will show the 
    ## signal/slot binding is success or failed
    print QObject.connect(c,SIGNAL('mWorkDoneSignal()'),d,SLOT('display()'))
    c.start()
    d.show()
    app.exec_()

在 C++ 中,QObject::connect 返回值将显示信号/插槽绑定是否成功。在 PyQt 中,返回值为 True,但不会触发插槽。我的问题:1)信号应该是类成员还是实例成员?2)如果 QObject.connect 的返回值不能给出绑定成功与否的提示,有没有其他方法可以检测到呢?我想在信号发送器和槽接收器之外绑定信号/槽,所以我更喜欢使用 QObject.connect 方式。但是我怎样才能正确地写这个,我尝试了以下方法,都失败了。

 QObject.connect(c,SIGNAL('mWorkDoneSignal'),d,SLOT('display'))
 QObject.connect(c,SIGNAL('mWorkDoneSignal()'),d,SLOT('display()'))
4

1 回答 1

1

首先,你真的应该在 pyqt 中使用新风格的信号。事实上,在 PyQt5 中QObject.connect甚至QObject.emit不再存在。

def __init__(self,parent = None):
    super(workThread,self).__init__(parent)
    self.mWorkDoneSignal = pyqtSignal()

这会创建一个未绑定的信号并将其分配给实例变量mWorkDoneSignal,但实际上并没有效果。如果你想创建一个信号,那么你真的必须在类上声明它。

所以如果你没有真正在这里创建信号,那么为什么这个调用会成功:

QObject.connect(c,SIGNAL('mWorkDoneSignal()'),d,SLOT('display()'))

答案在于PyQt4对旧式信号的处理:

发出 PyQt4 信号的行为隐含地定义了它。

因此,当您将信号连接到插槽时,只会检查插槽是否存在。信号本身此时并不真正需要存在,因此调用将始终成功,除非插槽不存在。

我尝试了以下方法,都失败了。

QObject.connect(c,SIGNAL('mWorkDoneSignal'),d,SLOT('display'))
QObject.connect(c,SIGNAL('mWorkDoneSignal()'),d,SLOT('display()'))

第一个失败是因为display(没有括号)不是有效的插槽。
第二个成功。它不起作用的原因是因为你发出mWorkDoneSignal了,但你真正需要发出的是:

self.emit(SIGNAL("mWorkDoneSignal()"))

使用新风格的信号,没有办法搞砸这样的事情:

from utils import sigint
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time

class workThread(QThread):

    mWorkDoneSignal = pyqtSignal()

    def __init__(self,parent = None):
        super(workThread,self).__init__(parent)

    def run(self):
        print "workThread start"
        time.sleep(1)
        print "workThread stop"
        self.mWorkDoneSignal.emit()

class MainWidget(QWidget):
    def __init__(self , parent = None):
        super(MainWidget,self).__init__(parent)

    @pyqtSlot()
    def display(self):
        print "dispaly"

if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    c = workThread()
    d = MainWidget()
    c.mWorkDoneSignal.connect(d.display)
    c.start()
    d.show()
    app.exec_()
于 2013-07-21T20:08:14.613 回答