【问题标题】:The difference between PyQt and Qt when handling user defined signal/slotPyQt和Qt在处理用户定义的信号/槽时的区别
【发布时间】:2013-07-20 06:38:57
【问题描述】:

嗯,我对 Qt 很熟悉,但是在使用 PyQt 时,signal/slot 的语法真的让我很困惑。 使用 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()'))

【问题讨论】:

    标签: pyqt signals slot


    【解决方案1】:

    首先,您应该真正将new style signals 与pyqt 一起使用。事实上,QObject.connectQObject.emit 将不再存在 in PyQt5

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

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

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

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

    答案就在 PyQt4 的 handling of old style signals 中:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-08
      • 1970-01-01
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      相关资源
      最近更新 更多