0

私は 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()'))
4

1 に答える 1

1

まず、pyqt で新しいスタイルのシグナルを実際に使用する必要があります。実際、PyQt5QObject.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(括弧なしで) が有効なスロットではないため、最初は失敗します。
2番目は成功します。動作しない理由は、を発行するためですが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 に答える